Mekicha
Mekicha

Reputation: 851

Serialize Many to Many Relationship with Extra fields

Please I'm stuck trying to get around this issue. Guess there is something I'm not getting after looking at other similar questions.

I have these models:

class Dish(BaseModel):
    class Meta:
        verbose_name_plural = 'dishes'
    name = models.CharField(_('dish'), max_length=100)
    dish_type = models.CharField(_("dish type"), max_length=100)
    price = models.PositiveIntegerField(_("price"))

    def __str__(self):
        return f"{self.name} costs {self.price}"


class Order(BaseModel):

    dishes = models.ManyToManyField(Dish, through='DishOrder')
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    discount = models.PositiveIntegerField(_("total discount"), blank=True)
    total = models.PositiveIntegerField(_("total"), blank=True)
    shipping = models.PositiveIntegerField(_("shipping cost"), blank=True)
    grand_total = models.PositiveIntegerField(_("grand total"), blank=True)
    country = models.CharField(_('country code'), max_length=2)

    def __str__(self):
        return f"order from {self.customer} at {self.total}"

    def get_absolute_url(self):
        return reverse('order-details', kwargs={'pk': self.pk})


class DishOrder(models.Model):
    dish = models.ForeignKey(Dish, on_delete=models.CASCADE, related_name='dishes')
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='dishes')
    quantity = models.PositiveIntegerField(_("quantity"))
    discount = models.PositiveIntegerField(_("discount"))
    price = models.PositiveIntegerField(_('price'))

And the corresponding serializers like so:

class DishOrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = DishOrder
        fields = (
            "quantity",
            "discount",
            "price"
        )

class OrderSerializer(serializers.ModelSerializer):
    dishes = DishOrderSerializer(source='dish', many=True)
    class Meta:
        model = Order
        fields = (
            "id",
            "country",
            "customer",
            "dishes", 
            "total", 
            "discount",
            "grand_total",
            "voucher"
        )

So as can be seen, I have a m2m relationship via a through table. However I can't get the serializer to work. This is the error I keep getting:

Got AttributeError when attempting to get a value for field dishes on serializer OrderSerializer. 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 'dish'.

I have been looking through this for some time trying to figure out what the error is. I will appreciate any help

Upvotes: 4

Views: 2745

Answers (1)

neverwalkaloner
neverwalkaloner

Reputation: 47354

Since you are using related_name='dishes' in model you should use dishes as source to the manytomany objects:

class OrderSerializer(serializers.ModelSerializer):
    dishes = DishOrderSerializer(source='dishes', many=True)

or simple:

class OrderSerializer(serializers.ModelSerializer):
    dishes = DishOrderSerializer(many=True)

Since source='dishes' redundant in case you named serializer's field dishes also.

Upvotes: 4

Related Questions