Quantcast
Channel: Planet Python
Viewing all articles
Browse latest Browse all 23354

Simple is Better Than Complex: How to Save Extra Data to a Django REST Framework Serializer

$
0
0

In this tutorial you are going to learn how to pass extra data to your serializer, before saving it to the database.

Introduction

When using regular Django forms, there is this common pattern where we save the form with commit=False and then pass some extra data to the instance before saving it to the database, like this:

form=InvoiceForm(request.POST)ifform.is_valid():invoice=form.save(commit=False)invoice.user=request.userinvoice.save()

This is very useful because we can save the required information using only one database query and it also make it possible to handle not nullable columns that was not defined in the form.

To simulate this pattern using a Django REST Framework serializer you can do something like this:

serializer=InvoiceSerializer(data=request.data)ifserializer.is_valid():serializer.save(user=request.user)

You can also pass several parameters at once:

serializer=InvoiceSerializer(data=request.data)ifserializer.is_valid():serializer.save(user=request.user,date=timezone.now(),status='sent')

Example Using APIView

In this example I created an app named core.

models.py

fromdjango.contrib.auth.modelsimportUserfromdjango.dbimportmodelsclassInvoice(models.Model):SENT=1PAID=2VOID=3STATUS_CHOICES=((SENT,'sent'),(PAID,'paid'),(VOID,'void'),)user=models.ForeignKey(User,on_delete=models.CASCADE,related_name='invoices')number=models.CharField(max_length=30)date=models.DateTimeField(auto_now_add=True)status=models.PositiveSmallIntegerField(choices=STATUS_CHOICES)amount=models.DecimalField(max_digits=10,decimal_places=2)

serializers.py

fromrest_frameworkimportserializersfromcore.modelsimportInvoiceclassInvoiceSerializer(serializers.ModelSerializer):classMeta:model=Invoicefields=('number','amount')

views.py

fromrest_frameworkimportstatusfromrest_framework.responseimportResponsefromrest_framework.viewsimportAPIViewfromcore.modelsimportInvoicefromcore.serializersimportInvoiceSerializerclassInvoiceAPIView(APIView):defpost(self,request):serializer=InvoiceSerializer(data=request.data)serializer.is_valid(raise_exception=True)serializer.save(user=request.user,status=Invoice.SENT)returnResponse(status=status.HTTP_201_CREATED)

Example Using ViewSet

Very similar example, using the same models.py and serializers.py as in the previous example.

views.py

fromrest_framework.viewsetsimportModelViewSetfromcore.modelsimportInvoicefromcore.serializersimportInvoiceSerializerclassInvoiceViewSet(ModelViewSet):queryset=Invoice.objects.all()serializer_class=InvoiceSerializerdefperform_create(self,serializer):serializer.save(user=self.request.user,status=Invoice.SENT)

Viewing all articles
Browse latest Browse all 23354

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>