Reputation: 16460
Where can I set the associated model when I'm creating an object in APIView
?
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
The above works in generics.ListAPIView
but what about APIView
? I have two models A
and B
. B
has a ForeignKey
to A
. When creating an instance of B
how do I set the ForeignKey
before saving?
a = A.objects.get(id=request.DATA['a_id'])
serializer = BSerializer(data=request.DATA)
if serializer.is_valid():
b = serializer.save(a=a)
If I include the a
field in BSerializer
, this complains that a This field is required
. If I exclude it, then it gives an IntegrityError
. How is it supposed to be done?
Upvotes: 4
Views: 6462
Reputation: 41719
For Django REST Framework 3.0:
perform_create
is available through the generics API, which is why it works for GenericAPIView
and any subclasses (including ViewSet
instances).
The error you are getting is on the serializer level, before you even reach the point of serializer.save
, so having perform_create
wouldn't completely help you there. If the user will never be submitting the full nested representation of the object (and your serializer is expecting one), then your best bet is to make the field read_only
and deal with it outside of the serializer by passing it into the serializer.save
method.
For Django REST Framework 2.4:
perform_create
is new in Django REST Framework 3.0, so the current documentation does not match the version you are using. If you can upgrade to Django REST Framework 3.0, it is recommended to do that.
In Django REST Framework 2.4, the serializer contains a reference to the model object that is being created or modified in the serializer.object
attribute. For a ModelSerializer
, this is the model object with any changes that were passed in (assuming it passed validation). Calling serializer.save
just saves this object (while reconstructing relations), so you can modify it directly.
To set a foreign key relationship that is required when the object is saved or created, you just need to do...
serializer.object.related_field = related_object
...before calling serializer.save()
(with no arguments). In Django REST Framework 2.4, any arguments passed to serializer.save
make their way down to model.save
, which is why you cannot use the method recommended for Django REST Framework 3.0. In 3.0, serializer.save
allows you to pass extra arguments that will be set directly on the object that should be created (a better way of setting serializer.validated_data
), instead of passing them into model.save
.
Upvotes: 9