带有Django ManyToMany模型的Factory Boy

时间:2019-06-27 21:26:43

标签: python django factory-boy

我在同一模块app.models.py上有3个模型,如下所示。其他一些模型可能会出现在代码中,但并不相关。

可选

class Optional(models.Model):
    name = models.CharField(_('Nome'), max_length=255)
    type = models.CharField(_('Tipo'), max_length=50, null=True, blank=True)
    description = models.TextField(_('Descrição'), null=True, blank=True)
    provider = models.ForeignKey('providers.Provider', null=True, blank=True)
    charge = models.ForeignKey('Charge', null=True, blank=True)

    def __str__(self):
        return self.name

覆盖率

class Coverage(models.Model):
    code = models.CharField(_('Código'), max_length=20, null=True, blank=True)
    vehicle_code = models.CharField(_('Código do veículo (ACRISS)'), max_length=4, null=True, blank=True)
    charge = models.ForeignKey('Charge', null=True, blank=True)

车辆

class Vehicle(models.Model):

    code = models.CharField(_('Código'), max_length=100)
    description = models.CharField(_('Descrição'), max_length=255, null=True, blank=True)
    model = models.CharField(_('Modelo'), max_length=100, null=True, blank=True)
    brand = models.CharField(_('Fabricante'), max_length=100, null=True, blank=True)
    group = models.ForeignKey('Group', null=True, blank=True)
    optionals = models.ManyToManyField('Optional', related_name='vehicle_optional')
    coverages = models.ManyToManyField('Coverage', related_name='vehicle_coverage')

    def __str__(self):
        return self.code

我正在尝试使用factory_boy从该模型创建灯具。

class CoverageFactory(factory.Factory):
    class Meta:
        model = Coverage
    charge = factory.SubFactory(ChargeFactory)

class OptionalFactory(factory.Factory):
    class Meta:
        model = Optional
    provider = factory.SubFactory(ProviderFactory)
    charge = factory.SubFactory(ChargeFactory)

class VehicleFactory(factory.Factory):
    class Meta:
        model = Vehicle
    group = factory.SubFactory(GroupFactory)
    optionals = factory.SubFactory(OptionalFactory)
    coverages = factory.SubFactory(CoverageFactory)

在我的测试中,它是通过以下方式实例化的:

optional = OptionalFactory(
    name="GPS",
    type="13",
    description="",
    charge=charge,
    provider=provider
)

coverage = CoverageFactory(
    code="ALI",
    vehicle_code="ABCD",
    charge=charge
)

vehicle = VehicleFactory(
    code="ECMM",
    description="GRUPO AX - MOVIDA ON",
    model="MOBI LIKE, OU SIMILAR",
    brand="",
    optionals=optional,
    coverages=coverage
)

当我使用pytest-django运行测试时,出现此错误。

ValueError: "<Vehicle: ECMM>" needs to have a value for field "id" before this many-to-many relationship can be used.

我已阅读有关Simple Many-to-many relationshipMany-to-many relation with a ‘through’的factory_boy文档,但无法修复。

2 个答案:

答案 0 :(得分:1)

  

调用UserFactory()或UserFactory.build()时,没有组绑定   将被创建。

     

但是当UserFactory.create(groups =(group1,group2,group3))是   调用后,groups声明会将以分组方式传递的组添加到   用户分组。

当您

时将生成id字段
optional = OptionalFactory.create(  # note the .create()
    name="GPS",
    type="13",
    description="",
    charge=charge,
    provider=provider
)

然后当您

vehicle = VehicleFactory.create(
    ...
    optionals=(optional,),
)

可以建立多对多optionals。还请注意,可选参数的参数为​​(optionals,)。函数期望可迭代

答案 1 :(得分:1)

您已经在文档中指出了正确的位置,该位置应该有效:https://factoryboy.readthedocs.io/en/latest/recipes.html#simple-many-to-many-relationship

class VehicleFactory(factory.Factory):
    ...
    # no optionals subfactory here
    ...

    @factory.post_generation
    def optionals(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return

        if extracted:
            # A list of groups were passed in, use them
            for optional in extracted:
                self.groups.add(optional)

然后您会打电话给类似的东西

VehicleFactory.create(optionals=[optional1, optional2])

希望能回答这个问题?如果没有更多有关在文档中尝试解决方案时不起作用的信息,将很难为您提供帮助