Reputation: 3755
I have a model that looks like this:
class Profile(models.Model):
following = models.ManyToManyField('Profile', related_name='followed')
admin_notes = models.TextField()
And a Django Rest Framework serializer that looks like this:
class ProfileSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Profile
fields = '__all__'
When creating a new Profile
I want to interrupt the save/create to set admin_notes
programmatically. I know how do to this inside a function-based view, but I am using DRF's viewsets this time and so I want to do this inside the serializer. The self-referential relationship is giving me trouble, though.
I tried this within the ProfileSerializer
:
def create(self, **validated_data):
p = Profile(**validated_data)
p.admin_notes = 'Test'
p.save()
This, as well as trying Profile.objects.create
instead of just making a new Profile
instance in the first line, resulted in the following error:
Exception Value: "<Profile>" needs to have a value for field "id" before this many-to-many relationship can be used.
Trying this:
def create(self, validated_data):
validated_data['admin_notes'] = 'Test'
return super(ProfileSerializer, self).create(**validated_data)
Results in this error:
Exception Value: create() got an unexpected keyword argument 'following'
I understand that Django creates m2m relationships in a two-step-save process, so the error makes sense but still leaves me stumped as to how I can move forward. How can I set the value of admin_notes
within the serializer given the way my model is set up?
Upvotes: 1
Views: 5685
Reputation: 341
Try this (assuming that you are passing the ids of the Profile instances to your m2m field):
def create(self, validated_data):
# First, remove following from the validated_data dict...
following_data = validated_data.pop('following', None)
# Set the admin_notes custom value...
validated_data['admin_notes'] = 'Test'
# Create the object instance...
profile = Profile.objects.create(**validated_data)
# Finally, add your many-to-many relationships...
if following_data:
for data in following_data:
profile.followed.add(Profile.objects.get(**data))
return profile
Upvotes: 3