Hossam Salah
Hossam Salah

Reputation: 185

Serialize related models and override the create method

I am new to DRF and I want to do something similar to the formsets in django forms I have an Invoice And Products models related to each other throw a many to many InvoiceDetail model.. when I create an Invoice I choose some products and create a InvoiceDetail object for each .. I want to do this in DRF how can I serialize the Invoice model and it's create function then? or should i do it form the view?

models.py:

 class Invoices(models.Model):
     #some fields
     products = models.ManyToManyField('Products', through='InvoiceDetail')


class Products(models.Model):
    #some fields


class InvoiceDetail(models.Model):
    invoice = models.ForeignKey(Invoices, related_name='parent_invoice')
    product = models.ForeignKey(Products, related_name='parent_product')
    product_description = models.TextField()
    product_price = models.DecimalField(max_digits=9, decimal_places=2)
    quantity_sold = models.IntegerField()

serializers.py:

class ProductsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Products
        fields = ('barcode', 'product_code', 'name', 'description', 'category',
                  'quantity_in_stock', 'quantity_on_hold', 'expire_date',
                  'vendor', 'manufacturer', 'discount')


class InvoiceDetailsSerializer(serializers.ModelSerializer):
    class Meta:
        model = InvoiceDetail
        fields = '__all__'

view.py:

class ProductsView(viewsets.ReadOnlyModelViewSet):
    queryset = Products.objects
    serializer_class = ProductsSerializer


class InvoicesView(viewsets.ModelViewSet):
    queryset = Invoices.objects
    serializer_class = InvoicesSerializer



class InvoiceDetailView(viewsets.ModelViewSet):
    queryset = InvoiceDetail.objects
    serializer_class = InvoiceDetailsSerializer

Upvotes: 0

Views: 2136

Answers (1)

zaidfazil
zaidfazil

Reputation: 9235

You could do this in the serializer itself,

class InvoiceSerializer(serializers.ModelSerializer):
    products = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all(), many=True)
    class Meta:
        model = Invoice
        fields = [ f.name for f in model._meta.fields ] + ['products']

    def create(self, validated_data):
        products = validated_data.pop('products')
        invoice = super(InvoiceSerializer, self).create(validated_data)
        for product in products:
            InvoiceDetail.objects.create(invoice=invoice, product=product)
        return invoice

This, is just a basic example for to know about how this works. You could customise it however you need.

Upvotes: 1

Related Questions