You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+pytest测试报错:ManyRelatedManager无title属性求助

解决Django多对多关系下pytest测试的AttributeError问题

问题场景

使用pytest测试Django API时触发错误:AttributeError: 'ManyRelatedManager' object has no attribute 'title'。错误出现在测试用例中直接访问order_created.product.title,因为Order与Product是多对多关联关系。

测试代码

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'

模型代码

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

错误原因

Django中多对多字段默认返回ManyRelatedManager对象,而非单个模型实例。直接访问order.product.title相当于在管理器对象上调用title属性,自然会触发属性不存在的错误。另外当前fixture创建的Order并未关联任何Product(违反了模型中blank=False的约束),这也是潜在问题。

解决方案

1. 修复Fixture,关联产品到订单

修改order_created fixture,在创建Order时关联之前生成的product1:

@pytest.fixture
def order_created():
    user1 = UserFactory(username='Lucas')
    category = CategoryFactory(title='teste')
    product1 = ProductFactory(title='teste_product')
    # 创建订单并关联产品
    order = OrderFactory(customer=user1)
    order.product.add(product1)
    return order

如果使用FactoryBoy,也可以直接通过字段传值关联:

# 假设OrderFactory支持多对多字段传值
return OrderFactory(customer=user1, product=[product1])

2. 修改测试用例的断言逻辑

根据业务需求选择合适的断言方式:

  • 检查是否存在指定产品:适用于不关心数量只关心是否关联的场景
@pytest.mark.django_db
def test_order_product_name(order_created):
    assert order_created.product.filter(title='teste_product').exists()
  • 获取单个产品断言:确定订单只关联一个产品时使用
@pytest.mark.django_db
def test_order_product_name(order_created):
    assert order_created.product.first().title == 'teste_product'
  • 检查所有关联产品的标题:适用于需要验证多个产品的场景
@pytest.mark.django_db
def test_order_product_name(order_created):
    product_titles = [p.title for p in order_created.product.all()]
    assert 'teste_product' in product_titles

内容的提问来源于stack exchange,提问作者Mateus Diniz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 07:19:59