Search code examples
pythondjangounit-testingdjango-modelspytest-django

AttributeError: 'ManyRelatedManager' object has no attribute 'title'


I was trying to make some tests in an API Django with pytest, but find this error: Attribute error image

Here's the code's test that failed:

import pytest
from core.orders.factories import *


@pytest.fixture
def order_created():
    user1 = UserFactory(username='Lucas')
    category = CategoryFactory(title='teste')
    product1 = ProductFactory(title='teste_product')
    return OrderFactory(customer=user1)


@pytest.mark.django_db
def test_order_customer_name(order_created):
    assert order_created.customer.username == 'Lucas'


@pytest.mark.django_db
def test_order_product_name(order_created):
    assert order_created.product.title == 'teste_product'

Searching into web I found this error is related to method ManyToManyField() from models. If helps, I'll also put my model's code here:

from django.db import models

from django.db import models
from django.contrib.auth.models import User

class Category(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
description = models.TextField(max_length=200, blank=True, null=True)
active = models.BooleanField(default=True)

    def __str__(self):
        return self.title

class Product(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(max_length=500, blank=True, null=True)
price = models.PositiveIntegerField(null=True)
active = models.BooleanField(default=True)
category = models.ManyToManyField(Category, blank=True)

    def __str__(self):
        return self.title

class Order(models.Model):
product = models.ManyToManyField(Product, blank=False)
customer = models.ForeignKey(User, on_delete=models.CASCADE, null=False)

    def __str__(self):
        return self.customer.name

I try to remove the lines of category1 and product1 delcaration from test code, but I really need find a way to verify the instances of a Order in terms of Product (that needs a category) and Customer(no problem whit that since I was trying to run the tests).

If someone knows how to solve this problem, I would be very grateful with your help! :D


Solution

  • You cannot access the property of another object from Many to Many mapping. Also the way you are trying to access title is wrong. Since in Many to Many field there can be multiple objects, while you are trying to access an attribute as if only one instance of product object is present there.

    What you should be doing is iterate over products from order. To iterate on products, you cannot iterate directly. i.e. You'll need to get all the products from order and then iterate on them. You can refer this answer for that: ManyRelatedManager not Iterable. Think I'm trying to pull my objects out incorrectly

    To answer you error above what you should be doing is as follows:

    products = order_created.product.all()
    for product in products:
        assert product.title == "expected title"