I have a Club Model as well as an Address model.
class Club(models.Model):
name = models.CharField(max_length=100)
owner = models.ForeignKey(UserAccount,on_delete=models.CASCADE,related_name = 'owner_of')
##members = models.ManyToManyField(UserAccount,related_name = 'member_of')
##staff = models.ManyToManyField(UserAccount,related_name = 'staff_of')
def __str__(self):
return f'{self.name}'
class Address(models.Model):
name = models.CharField(max_length=100)
street = models.CharField(max_length=150)
city = models.CharField(max_length=100)
state = models.CharField(max_length=100, blank=True, null=True) # Optional for countries without states
province = models.CharField(max_length=100, blank=True, null=True) # Optional for countries without provinces
country = models.CharField(max_length=50)
postal_code = models.CharField(max_length=20)
club = models.ForeignKey(Club,on_delete=models.CASCADE,related_name = 'address')
def __str__(self):
return f'{self.name}'
They have their respected serializers.
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = ['id', 'name', 'street', 'city', 'state', 'province', 'postal_code', 'country']
def create(self,validated_data):
user=self.context['user']
club=Club.objects.get(owner=user)
address=Address.objects.create(club=club,**validated_data)
return address
class ClubSerializer(serializers.ModelSerializer):
class Meta:
model = Club
fields = ['id', 'name']
def create(self,validated_data):
user=self.context['user']
club=Club.objects.create(owner=user,**validated_data)
return club
class ClubRegistrationSerializer(serializers.Serializer):
address= AddressSerializer2()
club=ClubSerializer2()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# We pass the "upper serializer" context to the "nested one"
self.fields['address'].context.update(self.context)
self.fields['club'].context.update(self.context)
this is the data that I am posting
{
"club":{"name":"someclub"},
"address":{
"name":"Bodrum Location",
"street":"140",
"city":"bodrum",
"state":"california",
"province":"some provence",
"postal_code":"123",
"country":"USA"
}
}
I can easily implement the create method of my view and
do this:
@action(detail=False,methods=['post'])
def register(self, request):
serializer = ClubRegistrationSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
clubinfo_data=serializer.validated_data.pop("club")
club_serializer=ClubSerializer(data=clubinfo_data)
club_serializer.is_valid(raise_exception=True)
club=club_serializer.save(owner=self.request.user)
address_data=serializer.validated_data.pop("address")
address_serializer=AddressSerializer(data=address_data)
address_serializer.is_valid(raise_exception=True)
address=address_serializer.save(club=club)
response={}
response['address']={}
response['address']['name']=address.name
response['address']['id']=address.id
response['address']['postal_code']=address.postal_code
response['club']={}
response['club']['name']=club.name
response['club']['id']=club.id
return Response(response, status=status.HTTP_201_CREATED)
- But from what I read it is not ideal to do the logic in views but in serializers.
So I can move the create method from my view’s create to serializer’s create.
But what does not make sense to me is that I can not call the create method of the nested serializers. Actually I could not even get the nested serializer objects so I can call its create method . You can think of this as if you are traversing a tree and calling create methods of each serializer and if they have create they call its child.
Ideally I should not implement all the logic in ClubRegistrationSerializer’s create method.
each serializer should be responsible for its own.
I should be able to call the create method of ClubRegistrationSerializer and that should call the create method of Address and Club’s serializers.
Every example I see handles all the logic in the parent serializer’s create.
- Secondly how can I call the ClubRegistrationSerializer with the address obj and club obj and get the data to send it to the user so that reponse would have the IDs.
I have tried ClubRegistrationSerializer(address=addressOBJ,club=clubOBJ)
like so
but this is throwing an exception.
Currently I am creating a dict and attaching the model’s values.
This is the response I would like to get from the serializer.
{"club":{"name":"someclub","id":"1"},
"address":{
"id":"1",
"name":"Some Location",
"street":"140",
"city":"San Fran",
"state":"california",
"province":"some province",
"postal_code":"123",
"country":"USA"
}
}