我正在为我的模型使用工厂男孩。另一个模型有一个外键,该模型的第一个 obj 用于模型的字符串表示。示例结构:
class A(models.Model):
...
def __str__(self):
return self.reverseForeignKey_set.first().name
class AFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.A
some_attribute = factory.RelatedFactory(
ReverseModelFactory,
'a',
)
但是当我使用 factory_boy 创建时,它给了我这个错误:
Traceback (most recent call last):
File "/home/rahul/Documents/projects/healbot_current/healbot/functional_tests/tests.py", line 21, in setUp
factories.AFactory.create()
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/base.py", line 623, in create
return cls._generate(True, attrs)
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/base.py", line 554, in _generate
results[name] = decl.call(obj, create, extraction_context)
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/declarations.py", line 624, in call
return factory.simple_generate(create, **passed_kwargs)
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/base.py", line 709, in simple_generate
return cls.generate(strategy, **kwargs)
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/base.py", line 676, in generate
return action(**kwargs)
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/base.py", line 622, in create
attrs = cls.attributes(create=True, extra=kwargs)
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/base.py", line 449, in attributes
utils.log_repr(extra),
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/factory/utils.py", line 142, in log_repr
return compat.force_text(repr(obj))
File "/home/rahul/Envs/healbot/lib/python3.6/site-packages/django/db/models/base.py", line 588, in __repr__
u = six.text_type(self)
File "/home/rahul/Documents/projects/healbot_current/healbot/diagnosis/models.py", line 57, in __str__
return self.reverseForeignKey_set.first().name
AttributeError: 'NoneType' object has no attribute 'name'
我能做些什么来解决这个问题吗?喜欢为 factory_boy覆盖模型 A 上的str方法?
你有这样的问题,因为A
模型实例比ReverseModel
实例更早创建。
正如 factory_boy 文档所说:
相关工厂:在构建/创建第一个工厂之后构建或创建给定工厂。
见http://factoryboy.readthedocs.io/en/latest/reference.html#post-generation-hooks
首先,您应该创建您ReverseModel
的A
模型实例,然后是您的模型实例。正如 factory_boy 文档在接收中所说:
当一个属性实际上是一个复杂字段(例如,另一个模型的外键)时,使用 SubFactory 声明
因此,您可以为 FK 模型定义一个工厂,并将其定义为 AFactory 中的 SubFactory。
# models.py
class A(models.Model):
...
def __str__(self):
return self.reverseForeignKey_set.first().name
# factories.py
import factory
from . import models
class ReverseModelFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.ReverseModel
# Define your model fields
attr = factory.Faker('text', max_nb_chars=255)
class AFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.A
some_attribute = factory.SubFactory(ReverseModelFactory)
在这种情况下,您的 ReverseModelFactory 对象将首先被创建来解决您的问题。有关更多信息,请参阅http://factoryboy.readthedocs.io/en/latest/recipes.html。
我还应该注意,如果你想处理 ManyToMany 字段,你应该使用 post_generation 钩子:
# models.py
class Group(models.Model):
name = models.CharField()
class User(models.Model):
name = models.CharField()
groups = models.ManyToManyField(Group)
# factories.py
class GroupFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Group
name = factory.Sequence(lambda n: "Group #%s" % n)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.User
name = "John Doe"
@factory.post_generation
def groups(self, create, extracted, **kwargs):
if not create:
# Simple build, do nothing.
return
if extracted:
# A list of groups were passed in, use them
for group in extracted:
self.groups.add(group)
有关更多信息,请参阅http://factoryboy.readthedocs.io/en/latest/recipes.html#simple-many-to-many-relationship。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句