I am using DRF and I'm trying to create an object which has several foreign keys as well as related objects that will need creating in the process.
Here's what a reduced version of my models looks like:
class Race(models.Model):
name = models.CharField(max_length=200)
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='races')
type = models.ForeignKey(Type, on_delete=models.SET_NULL, related_name='races', null=True)
region = models.ForeignKey(Region, on_delete=models.CASCADE, verbose_name=_('region'), related_name='races')
country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name='races')
timezone = models.ForeignKey(Timezone, on_delete=models.SET_NULL, null=True)
class Event(models.Model):
name = models.CharField(max_length=200)
race = models.ForeignKey(Race, on_delete=models.CASCADE, related_name='events')
And then here's my Race serializer:
class RaceSerializer(serializers.ModelSerializer):
owner = UserSerializer(read_only=True)
type = TypeSerializer(read_only=True)
events = EventSerializer(many=True)
country = CountrySerializer()
region = RegionSerializer(read_only=True)
timezone = TimezoneSerializer(read_only=True)
def create(self, validated_data):
with transaction.atomic():
events = validated_data.pop('events', None)
race = Race(**validated_data)
race.save()
for event in events:
Event.objects.create(race=race, **event)
return race
And my view:
class AddRaceView(CreateAPIView):
serializer_class = RaceSerializer
permission_classes = (IsAuthenticated,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
And here's some test data I'm sending with my POST request:
{
"name": "ABC Marathon",
"country": {
"pk": 1,
"name": "United States"
},
"region": {
"pk": 1,
"code": "ME"
},
"timezone": {
"pk": 1,
"code": "EST"
},
"events": [
{
"name": "Marathon"
},
{
"name": "Half Marathon"
}
]
}
So the problem I'm having is passing valid data to the serializer for the foreign keys. I don't want to create new objects for Type, Region, Country, Timezone, only pass the appropriate data so the newly created Race object references existing foreign keys correctly.
Here's what I've tried:
1) Not setting read_only=True on the foreign key serializers. This attempts to create new objects that I don't want.
2) Setting read_only=True on the foreign key serializers (as in the code above). This helps with not attempting to create new Type, Region etc objects, but drops the respective fields from validated_data in the serializer create method. So I have no way to add the existing objects to the Race foreign keys on creation.
3) Using PrimaryKeyForeignField instead of TypeSerializer, RegionSerializer etc. But then when I use RaceSerializer to retrieve race data, I only have a pk under type, region etc and I'd really like to be able to retrieve all fields for the foreign keys.
Can you please advise on what the correct setup would look for something like this? I feel like it's shouldn't be as hard as this.
Thank you!