Why is pytest throwing an "AttributeError: 'NoneType' object has no attribute '_meta'" error when testing model creation?
Why is pytest throwing an "AttributeError: 'NoneType' object has no attribute '_meta'" error when testing model creation?
我正在使用 Django 2 并尝试为我的模型编写一些单元测试。我有这些模型...
class CoopTypeManager(models.Manager):
def get_by_natural_key(self, name):
return self.get_or_create(name=name)[0]
class CoopType(models.Model):
name = models.CharField(max_length=200, null=False, unique=True)
objects = CoopTypeManager()
class CoopManager(models.Manager):
# Look up by coop type
def get_by_type(self, type):
qset = Coop.objects.filter(type__name=type,
enabled=True)
return qset
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType)
address = AddressField(on_delete=models.CASCADE)
enabled = models.BooleanField(default=True, null=False)
phone = PhoneNumberField(null=True)
email = models.EmailField(null=True)
web_site = models.TextField()
我创建了以下工厂来自动生成这些模型...
import factory
from .models import CoopType, Coop
class CoopTypeFactory(factory.DjangoModelFactory):
"""
Define Coop Type Factory
"""
class Meta:
model = CoopType
class CoopFactory(factory.DjangoModelFactory):
"""
Define Coop Factory
"""
class Meta:
model = Coop
coop_type = factory.SubFactory(CoopTypeFactory)
然后我创建了这个简单的测试...
import pytest
from django.test import TestCase
from .tests.factories import CoopTypeFactory, CoopFactory
class ModelTests(TestCase):
@classmethod
def setUpTestData(cls):
print("setUpTestData: Run once to set up non-modified data for all class methods.")
pass
def setUp(self):
print("setUp: Run once for every test method to setup clean data.")
pass
@pytest.mark.django_db
def test_coop_type_model():
""" Test coop type model """
# create coop type model instance
coop_type = CoopTypeFactory(name="Test Coop Type Name")
assert coop_type.name == "Test Coop Type Name"
但是当我 运行 测试时,我得到一个错误,"AttributeError: 'NoneType' object has no attribute '_meta'"
(venv) localhost:web davea$ python manage.py test
Creating test database for alias 'default'...
Got an error creating the test database: (1007, "Can't create database 'test_maps_data'; database exists")
Type 'yes' if you would like to try deleting the test database 'test_maps_data', or 'no' to cancel: yes
Destroying old test database for alias 'default'...
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/test.py", line 26, in run_from_argv
super().run_from_argv(argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 335, in execute
output = self.handle(*args, **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/test.py", line 59, in handle
failures = test_runner.run_tests(test_labels)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/test/runner.py", line 601, in run_tests
old_config = self.setup_databases()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/test/runner.py", line 548, in setup_databases
self.parallel, **kwargs
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/test/utils.py", line 176, in setup_databases
serialize=connection.settings_dict.get('TEST', {}).get('SERIALIZE', True),
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/base/creation.py", line 76, in create_test_db
self.connection._test_serialized_contents = self.serialize_db_to_string()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/base/creation.py", line 119, in serialize_db_to_string
serializers.serialize("json", get_objects(), indent=None, stream=out)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/__init__.py", line 128, in serialize
s.serialize(queryset, **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/base.py", line 80, in serialize
for count, obj in enumerate(queryset, start=1):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/base/creation.py", line 116, in get_objects
yield from queryset.iterator()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/query.py", line 336, in _iterator
yield from self._iterable_class(self, chunked_fetch=use_chunked_fetch, chunk_size=chunk_size)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/query.py", line 54, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1050, in execute_sql
sql, params = self.as_sql()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 445, in as_sql
extra_select, order_by, group_by = self.pre_sql_setup()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 50, in pre_sql_setup
self.setup_query()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 40, in setup_query
self.query.get_initial_alias()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/query.py", line 886, in get_initial_alias
alias = self.join(BaseTable(self.get_meta().db_table, None))
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/query.py", line 284, in get_meta
return self.model._meta
AttributeError: 'NoneType' object has no attribute '_meta'
编辑: 如果您想尝试重现该问题,请点击此处 github link。项目在 "web" -- https://github.com/chicommons/maps
简单的解决方案是,在测试期间忽略迁移 运行。为此,为测试环境创建一个单独的设置模块
# /web/maps/test_settings.py
from .settings import *
class DisableMigrations(object):
# ref:
def __contains__(self, item):
return True
def __getitem__(self, item):
return None
MIGRATION_MODULES = DisableMigrations()
然后运行测试为,
python manage.py test <b>--settings=maps.test_settings</b>
- Screenshot
注意:我对存储库进行了其他小改动以完成它,但我希望这些事情不是什么大问题。 (反正我给你做了a PR here)
好的,我在 github 上查看了您的代码,我的第一个警告是:不要对其他包的模型进行 monkeypatch,如果可以的话,请子类化。
你对 django-address 的使用有点乱,你在使用模型并修改它们的行为,但它很危险。
罪名是
setattr(State._meta, 'default_manager', StateCustomManager())
setattr(Locality._meta, 'default_manager', LocalityCustomManager())
这些属性是私有的(因此 _
前缀 _meta
不应被混淆。我会改用 State.add_to_class('objects', StateCustomManager())
。
第二个警告是:我真的不认为你使用 get_by_natural_key()
和自动创建对象是非常明智的,它可能会减慢你的对象访问速度。
您没有在任何一个上调用 Supper class 构造函数
你派生的 classes。当你写一个派生的class时,一定要调用
子 class:
上的超级 class 构造函数
class SubClass(SupperClass):
def __init__(self, *args, **kwargs):
super(SubClass, self).__init__(*args, **kwargs)
我正在使用 Django 2 并尝试为我的模型编写一些单元测试。我有这些模型...
class CoopTypeManager(models.Manager):
def get_by_natural_key(self, name):
return self.get_or_create(name=name)[0]
class CoopType(models.Model):
name = models.CharField(max_length=200, null=False, unique=True)
objects = CoopTypeManager()
class CoopManager(models.Manager):
# Look up by coop type
def get_by_type(self, type):
qset = Coop.objects.filter(type__name=type,
enabled=True)
return qset
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType)
address = AddressField(on_delete=models.CASCADE)
enabled = models.BooleanField(default=True, null=False)
phone = PhoneNumberField(null=True)
email = models.EmailField(null=True)
web_site = models.TextField()
我创建了以下工厂来自动生成这些模型...
import factory
from .models import CoopType, Coop
class CoopTypeFactory(factory.DjangoModelFactory):
"""
Define Coop Type Factory
"""
class Meta:
model = CoopType
class CoopFactory(factory.DjangoModelFactory):
"""
Define Coop Factory
"""
class Meta:
model = Coop
coop_type = factory.SubFactory(CoopTypeFactory)
然后我创建了这个简单的测试...
import pytest
from django.test import TestCase
from .tests.factories import CoopTypeFactory, CoopFactory
class ModelTests(TestCase):
@classmethod
def setUpTestData(cls):
print("setUpTestData: Run once to set up non-modified data for all class methods.")
pass
def setUp(self):
print("setUp: Run once for every test method to setup clean data.")
pass
@pytest.mark.django_db
def test_coop_type_model():
""" Test coop type model """
# create coop type model instance
coop_type = CoopTypeFactory(name="Test Coop Type Name")
assert coop_type.name == "Test Coop Type Name"
但是当我 运行 测试时,我得到一个错误,"AttributeError: 'NoneType' object has no attribute '_meta'"
(venv) localhost:web davea$ python manage.py test
Creating test database for alias 'default'...
Got an error creating the test database: (1007, "Can't create database 'test_maps_data'; database exists")
Type 'yes' if you would like to try deleting the test database 'test_maps_data', or 'no' to cancel: yes
Destroying old test database for alias 'default'...
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/test.py", line 26, in run_from_argv
super().run_from_argv(argv)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/base.py", line 335, in execute
output = self.handle(*args, **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/management/commands/test.py", line 59, in handle
failures = test_runner.run_tests(test_labels)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/test/runner.py", line 601, in run_tests
old_config = self.setup_databases()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/test/runner.py", line 548, in setup_databases
self.parallel, **kwargs
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/test/utils.py", line 176, in setup_databases
serialize=connection.settings_dict.get('TEST', {}).get('SERIALIZE', True),
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/base/creation.py", line 76, in create_test_db
self.connection._test_serialized_contents = self.serialize_db_to_string()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/base/creation.py", line 119, in serialize_db_to_string
serializers.serialize("json", get_objects(), indent=None, stream=out)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/__init__.py", line 128, in serialize
s.serialize(queryset, **options)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/core/serializers/base.py", line 80, in serialize
for count, obj in enumerate(queryset, start=1):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/base/creation.py", line 116, in get_objects
yield from queryset.iterator()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/query.py", line 336, in _iterator
yield from self._iterable_class(self, chunked_fetch=use_chunked_fetch, chunk_size=chunk_size)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/query.py", line 54, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1050, in execute_sql
sql, params = self.as_sql()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 445, in as_sql
extra_select, order_by, group_by = self.pre_sql_setup()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 50, in pre_sql_setup
self.setup_query()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 40, in setup_query
self.query.get_initial_alias()
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/query.py", line 886, in get_initial_alias
alias = self.join(BaseTable(self.get_meta().db_table, None))
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/query.py", line 284, in get_meta
return self.model._meta
AttributeError: 'NoneType' object has no attribute '_meta'
编辑: 如果您想尝试重现该问题,请点击此处 github link。项目在 "web" -- https://github.com/chicommons/maps
简单的解决方案是,在测试期间忽略迁移 运行。为此,为测试环境创建一个单独的设置模块
# /web/maps/test_settings.py
from .settings import *
class DisableMigrations(object):
# ref:
def __contains__(self, item):
return True
def __getitem__(self, item):
return None
MIGRATION_MODULES = DisableMigrations()
然后运行测试为,
python manage.py test <b>--settings=maps.test_settings</b>
- Screenshot
注意:我对存储库进行了其他小改动以完成它,但我希望这些事情不是什么大问题。 (反正我给你做了a PR here)
好的,我在 github 上查看了您的代码,我的第一个警告是:不要对其他包的模型进行 monkeypatch,如果可以的话,请子类化。
你对 django-address 的使用有点乱,你在使用模型并修改它们的行为,但它很危险。
罪名是
setattr(State._meta, 'default_manager', StateCustomManager())
setattr(Locality._meta, 'default_manager', LocalityCustomManager())
这些属性是私有的(因此 _
前缀 _meta
不应被混淆。我会改用 State.add_to_class('objects', StateCustomManager())
。
第二个警告是:我真的不认为你使用 get_by_natural_key()
和自动创建对象是非常明智的,它可能会减慢你的对象访问速度。
您没有在任何一个上调用 Supper class 构造函数 你派生的 classes。当你写一个派生的class时,一定要调用 子 class:
上的超级 class 构造函数class SubClass(SupperClass):
def __init__(self, *args, **kwargs):
super(SubClass, self).__init__(*args, **kwargs)