Django Nested Serializers witj Foreign Field

I am trying to post this json request through postman

{   "name":"Someones order",
    "date_due": "2024-06-23T15:52:59Z",
    "customer":3,
    "orderItem":[{
        "item":1,
        "count":1
    }]
} 

I have implemented my models like so.

       class Item(models.Model):
            name = models.CharField(max_length=255) 
            price = models.DecimalField(max_digits=6, decimal_places=2)
            bakery = models.ForeignKey(Bakery,on_delete=models.CASCADE,related_name='items')
        
            def __str__(self):
                return f'{self.name}'
        
        class Order(models.Model):
        
            name = models.CharField(max_length=255) 
            bakery = models.ForeignKey(Bakery,on_delete=models.CASCADE,related_name='orders')
            customer = models.ForeignKey(Customer,on_delete=models.CASCADE,related_name='orders')
            date_created= models.DateTimeField(auto_now_add=True)
            date_due = models.DateTimeField()
            date_updated = models.DateTimeField(auto_now=True)
            #order_item = models.OneToOneField(OrderItem, on_delete=models.CASCADE,related_name='item_orderitems')
            def __str__(self):
                return f'{self.name}'
            
        class OrderItem(models.Model):
            bakery = models.ForeignKey(Bakery,on_delete=models.CASCADE,related_name='order_items')
            count = models.IntegerField()
            item = models.ForeignKey(Item, on_delete=models.CASCADE,related_name='item_orderitems')
            order = models.OneToOneField(Order, on_delete=models.CASCADE,related_name='orderitems')
            def __str__(self):
                return f'{self.name}'

Serializer is implemented as

class OrderItemCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItem
        fields = ['item','count']

class OrderCreateSerializer(serializers.ModelSerializer):
    
    orderItem=OrderItemCreateSerializer(many=True)
    class Meta:
        model = Order
        fields = ("name","date_due","customer","orderItem")
        
    def create(self, validated_data):
        print("create")
        print(validated_data)
        itemid=validated_data.pop("orderItem")
        print(itemid)
        bakery=self.context['request'].user.bakery
        customer=validated_data.pop("customer")
        
        print(customer)
        print("validated_data")
        print(validated_data)
        order=Order.objects.create(bakery=bakery,customer=customer,**validated_data)
        print("create 4")
        for items in itemid:
            print("create 5")
            OrderItem.objects.create(bakery=bakery,order=order,**items)
            print("create 6")
        print("returning")
        return order

When I make the post request i get

Got AttributeError when attempting to get a value for field orderItem on serializer OrderCreateSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Order instance. Original exception text was: 'Order' object has no attribute 'orderItem'.

I understand that Order model do not have a field pointing to orderitem but relation ship is rather reverse. But OrderCreateSerializer lists orderItem as a field.

I have implemented the same with a regular serializer instead of Modelserializer thinking that maybe it is complaining since it really is not part of the model.

But most important thing is that if you look at my print statements it prints "returning" and returns.

Should I implement the create method of the modelviewset and implement some of the logic there? would that help?

I would advise to stick to the framework features. The relation between Order and Item is m2m, since an extra fields is required, then its necessary to create a through table.

models.py

class Order(models.Model):
    ...
    item_list = models.ManyToManyField(
        Item,
        through="OrderItem",
    )


class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="items")
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()

serializers.py

class OrderItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItem
        fields = ["item", "quantity"]


class OrderSerializer(serializers.ModelSerializer):

    items = OrderItemSerializer(many=True)

    class Meta:
        model = Order
        fields = ("name", "bakery", "customer", "date_due", "items")

    def create(self, validated_data):
        items = validated_data.pop("items")
        order = super().create(validated_data)
        for obj in items:
            obj.update({"order": order})
            OrderItem.objects.create(**obj)
        return order

payload (you missed bakery key:value)

{
    "name": "Someones order",
    "date_due": "2024-06-23T15:52:59Z",
    "bakery": 1,
    "customer": 3,
    "items": [
        {
            "item": 1,
            "quantity": 1
        }
    ]
}

And, unless a Bakery has an unique item then having its FK in Item is a waste.

Вернуться на верх