用工厂男孩测试 Django 的外键不起作用
foreign key in testing django with factory boy doesn't work
我在 library factory boy 中遇到外键问题。我的测试没有执行
我认为是外键的问题。
我尝试测试 user.models 中的用户模型,这就是我的代码的样子
class Task(models.Model):
title = models.CharField(max_length=255, verbose_name='Заголовок')
description = models.CharField(max_length=255, verbose_name='Описание')
cost = models.DecimalField(max_digits=7, decimal_places=2, default=0, verbose_name='Цена')
assignee = models.ForeignKey('users.User', related_name='assignee', null=True, verbose_name='Исполнитель')
created_by = models.ForeignKey('users.User', related_name='created_by', verbose_name='Кем был создан')
def __str__(self):
return self.title
我用工厂小哥测试了一下我的工厂小哥 class 的样子
class UserFactoryCustomer(factory.Factory):
class Meta:
model = User
first_name = 'Ahmed'
last_name = 'Asadov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 1
balance = 10000.00
class UserFactoryExecutor(factory.Factory):
class Meta:
model = User
first_name = 'Uluk'
last_name = 'Djunusov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 2
balance = 5000.00
class TaskFactory(factory.Factory):
class Meta:
model = Task
title = factory.Sequence(lambda n: 'Title {}'.format(n))
description = factory.Sequence(lambda d: 'Description {}'.format(d))
cost = 5000.00
assignee = factory.SubFactory(UserFactoryExecutor)
created_by = factory.SubFactory(UserFactoryCustomer)
这是我测试的例子
class ApiModelTestCase(TestCase):
def test_creating_models_instance(self):
executor = factories.UserFactoryExecutor()
customer = factories.UserFactoryCustomer()
Task.objects.create(title="Simple Task", description="Simple Description", cost="5000.00",
assignee=executor, created_by=customer)
这是我的错误
ERROR: test_creating_models_instance (tests.test_models.ApiModelTestCase)
Traceback (most recent call last):
File "/Users/heartprogrammer/Desktop/freelance-with-api/freelance/tests/test_models.py", line 12, in test_creating_models_instance
assignee=executor, created_by=customer)
File "/Users/heartprogrammer/Documents/envs/freelance/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/heartprogrammer/Documents/envs/freelance/lib/python3.6/site-packages/django/db/models/query.py", line 394, in create
obj.save(force_insert=True, using=self.db)
File "/Users/heartprogrammer/Documents/envs/freelance/lib/python3.6/site-packages/django/db/models/base.py", line 763, in save
"unsaved related object '%s'." % field.name
ValueError: save() prohibited to prevent data loss due to unsaved related object 'assignee'.
该错误表明受让人实例未保存。试试这个
class ApiModelTestCase(TestCase):
def test_creating_models_instance(self):
executor = factories.UserFactoryExecutor.create()
customer = factories.UserFactoryCustomer.create()
Task.objects.create(title="Simple Task", description="Simple Description", cost="5000.00",
assignee=executor, created_by=customer)
更新:
If you work with Django models, you need to use factory.django.DjangoModelFactory — otherwise, factory_boy uses the "simple Python object" approach.
https://github.com/FactoryBoy/factory_boy/issues/329
所以应该是
from factory.django import DjangoModelFactory
class UserFactoryCustomer(DjangoModelFactory):
class Meta:
model = User
first_name = 'Ahmed'
last_name = 'Asadov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 1
balance = 10000.00
class UserFactoryExecutor(DjangoModelFactory):
class Meta:
model = User
first_name = 'Uluk'
last_name = 'Djunusov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 2
balance = 5000.00
我在 library factory boy 中遇到外键问题。我的测试没有执行 我认为是外键的问题。
我尝试测试 user.models 中的用户模型,这就是我的代码的样子
class Task(models.Model):
title = models.CharField(max_length=255, verbose_name='Заголовок')
description = models.CharField(max_length=255, verbose_name='Описание')
cost = models.DecimalField(max_digits=7, decimal_places=2, default=0, verbose_name='Цена')
assignee = models.ForeignKey('users.User', related_name='assignee', null=True, verbose_name='Исполнитель')
created_by = models.ForeignKey('users.User', related_name='created_by', verbose_name='Кем был создан')
def __str__(self):
return self.title
我用工厂小哥测试了一下我的工厂小哥 class 的样子
class UserFactoryCustomer(factory.Factory):
class Meta:
model = User
first_name = 'Ahmed'
last_name = 'Asadov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 1
balance = 10000.00
class UserFactoryExecutor(factory.Factory):
class Meta:
model = User
first_name = 'Uluk'
last_name = 'Djunusov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 2
balance = 5000.00
class TaskFactory(factory.Factory):
class Meta:
model = Task
title = factory.Sequence(lambda n: 'Title {}'.format(n))
description = factory.Sequence(lambda d: 'Description {}'.format(d))
cost = 5000.00
assignee = factory.SubFactory(UserFactoryExecutor)
created_by = factory.SubFactory(UserFactoryCustomer)
这是我测试的例子
class ApiModelTestCase(TestCase):
def test_creating_models_instance(self):
executor = factories.UserFactoryExecutor()
customer = factories.UserFactoryCustomer()
Task.objects.create(title="Simple Task", description="Simple Description", cost="5000.00",
assignee=executor, created_by=customer)
这是我的错误
ERROR: test_creating_models_instance (tests.test_models.ApiModelTestCase)
Traceback (most recent call last):
File "/Users/heartprogrammer/Desktop/freelance-with-api/freelance/tests/test_models.py", line 12, in test_creating_models_instance
assignee=executor, created_by=customer)
File "/Users/heartprogrammer/Documents/envs/freelance/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/heartprogrammer/Documents/envs/freelance/lib/python3.6/site-packages/django/db/models/query.py", line 394, in create
obj.save(force_insert=True, using=self.db)
File "/Users/heartprogrammer/Documents/envs/freelance/lib/python3.6/site-packages/django/db/models/base.py", line 763, in save
"unsaved related object '%s'." % field.name
ValueError: save() prohibited to prevent data loss due to unsaved related object 'assignee'.
该错误表明受让人实例未保存。试试这个
class ApiModelTestCase(TestCase):
def test_creating_models_instance(self):
executor = factories.UserFactoryExecutor.create()
customer = factories.UserFactoryCustomer.create()
Task.objects.create(title="Simple Task", description="Simple Description", cost="5000.00",
assignee=executor, created_by=customer)
更新:
If you work with Django models, you need to use factory.django.DjangoModelFactory — otherwise, factory_boy uses the "simple Python object" approach. https://github.com/FactoryBoy/factory_boy/issues/329
所以应该是
from factory.django import DjangoModelFactory
class UserFactoryCustomer(DjangoModelFactory):
class Meta:
model = User
first_name = 'Ahmed'
last_name = 'Asadov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 1
balance = 10000.00
class UserFactoryExecutor(DjangoModelFactory):
class Meta:
model = User
first_name = 'Uluk'
last_name = 'Djunusov'
username = factory.LazyAttribute(lambda o: slugify(o.first_name + '.' + o.last_name))
email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
user_type = 2
balance = 5000.00