Sam R.
Sam R.

Reputation: 16460

django-rest-framework - What is the equivalent of "perform_create" in APIView

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

Answers (1)

Kevin Brown-Silva
Kevin Brown-Silva

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

Related Questions