为什么 Django 管理模型页面在成功迁移后会引发 FieldDoesNotExist 异常?
为这个问题挠头。我只是向模型添加了一个新字段。
class Image(BaseModel):
url = models.URLField(max_length=1000, null=True)
content_type = models.ForeignKey(ContentType, on_delete=models.SET_NULL, null=True)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
# new field added below
class Type(models.TextChoices):
HEADER = 'HEADER', _('Header')
type = models.CharField(
max_length=20,
choices=Type.choices,
null=True,
blank=True
)
class Meta:
db_table = 'Image'
然后我运行了python manage.py makemigrations
,然后运行了python manage.py migrate
。这是成功的,我可以在数据库中的表上看到新字段。 django_migrations
表中的信息看起来正确。
这是我的迁移文件:
# Generated by Django 3.0.5 on 2022-03-23 12:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('example', '0082_auto_20220322_1937'),
]
operations = [
migrations.AddField(
model_name='image',
name='type',
field=models.CharField(blank=True, choices=[('HEADER', 'Header')], max_length=20, null=True),
),
]
这是我的图像管理文件:
from .base import BaseModelAdmin
class ImageAdmin(BaseModelAdmin):
list_display = ('id', 'url', 'content_type', 'content_object', 'type', 'is_deleted')
list_filter = ('is_deleted',)
这是 ImageAdmin 继承自的 BaseModelAdmin:
from django.contrib.contenttypes.admin import GenericTabularInline
from django.contrib import admin
class BaseModelAdmin(admin.ModelAdmin):
def get_actions(self, request):
actions = super(BaseModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
class BaseStackedInline(admin.StackedInline):
def get_actions(self, request):
actions = super(BaseModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
class BaseGenericTabularInline(GenericTabularInline):
def get_actions(self, request):
actions = super(BaseModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
这是图像模型继承自的 BaseModel:
from django.db import models
class BaseManager(models.Manager):
def get_or_none(self, *args, **kwargs):
try:
return self.get(*args, **kwargs)
except self.model.DoesNotExist:
return None
class BaseModel(models.Model):
is_deleted = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = BaseManager()
def __str__(self):
return F"ID: {self.id}"
class Meta:
abstract = True
我面临的问题是当我在 django admin 中访问该模型页面时,我收到以下内部服务器错误:
Traceback (most recent call last):
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 262, in lookup_field
example_app | f = _get_non_gfk_field(opts, name)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 297, in _get_non_gfk_field
example_app | raise FieldDoesNotExist()
example_app | django.core.exceptions.FieldDoesNotExist
example_app |
example_app | During handling of the above exception, another exception occurred:
example_app |
example_app | Traceback (most recent call last):
example_app | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 34, in inner
example_app | response = get_response(request)
example_app | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 145, in _get_response
example_app | response = self.process_exception_by_middleware(e, request)
example_app | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 143, in _get_response
example_app | response = response.render()
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/response.py", line 105, in render
example_app | self.content = self.rendered_content
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/response.py", line 83, in rendered_content
example_app | return template.render(context, self._request)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
example_app | return self.template.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 171, in render
example_app | return self._render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
example_app | return self.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
example_app | return compiled_parent._render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
example_app | return self.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
example_app | return compiled_parent._render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
example_app | return self.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
example_app | result = block.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
example_app | result = block.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/base.py", line 33, in render
example_app | return super().render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/library.py", line 214, in render
example_app | _dict = self.func(*resolved_args, **resolved_kwargs)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 342, in result_list
example_app | 'results': list(results(cl)),
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 318, in results
example_app | yield ResultList(None, items_for_result(cl, res, None))
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 309, in __init__
example_app | super().__init__(*items)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 232, in items_for_result
example_app | f, attr, value = lookup_field(field_name, result, cl.model_admin)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 273, in lookup_field
example_app | attr = getattr(obj, name)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/contenttypes/fields.py", line 243, in __get__
example_app | rel_obj = ct.get_object_for_this_type(pk=pk_val)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/contenttypes/models.py", line 175, in get_object_for_this_type
example_app | return self.model_class()._base_manager.using(self._state.db).get(**kwargs)
example_app | AttributeError: 'NoneType' object has no attribute '_base_manager'
我已多次尝试恢复迁移并重新运行它。我还查看了其他类似的问题,但没有一个解决方案有效或解决了我的具体问题。
为什么会发生这种情况?
Scratching my head on this one. I've simply added a new field to a model.
class Image(BaseModel):
url = models.URLField(max_length=1000, null=True)
content_type = models.ForeignKey(ContentType, on_delete=models.SET_NULL, null=True)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
# new field added below
class Type(models.TextChoices):
HEADER = 'HEADER', _('Header')
type = models.CharField(
max_length=20,
choices=Type.choices,
null=True,
blank=True
)
class Meta:
db_table = 'Image'
Then I ran python manage.py makemigrations
followed by python manage.py migrate
. This was successful and I can see the new field on the table in my database. The info from the django_migrations
table looks correct.
Here is my migration file:
# Generated by Django 3.0.5 on 2022-03-23 12:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('example', '0082_auto_20220322_1937'),
]
operations = [
migrations.AddField(
model_name='image',
name='type',
field=models.CharField(blank=True, choices=[('HEADER', 'Header')], max_length=20, null=True),
),
]
Here is my Image Admin File:
from .base import BaseModelAdmin
class ImageAdmin(BaseModelAdmin):
list_display = ('id', 'url', 'content_type', 'content_object', 'type', 'is_deleted')
list_filter = ('is_deleted',)
Here is the BaseModelAdmin that ImageAdmin inherits from:
from django.contrib.contenttypes.admin import GenericTabularInline
from django.contrib import admin
class BaseModelAdmin(admin.ModelAdmin):
def get_actions(self, request):
actions = super(BaseModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
class BaseStackedInline(admin.StackedInline):
def get_actions(self, request):
actions = super(BaseModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
class BaseGenericTabularInline(GenericTabularInline):
def get_actions(self, request):
actions = super(BaseModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
Here is the BaseModel that the Image model inherits from:
from django.db import models
class BaseManager(models.Manager):
def get_or_none(self, *args, **kwargs):
try:
return self.get(*args, **kwargs)
except self.model.DoesNotExist:
return None
class BaseModel(models.Model):
is_deleted = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = BaseManager()
def __str__(self):
return F"ID: {self.id}"
class Meta:
abstract = True
The problem I'm facing is when I visit that model page in the django admin, I get an internal server error with the following:
Traceback (most recent call last):
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 262, in lookup_field
example_app | f = _get_non_gfk_field(opts, name)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 297, in _get_non_gfk_field
example_app | raise FieldDoesNotExist()
example_app | django.core.exceptions.FieldDoesNotExist
example_app |
example_app | During handling of the above exception, another exception occurred:
example_app |
example_app | Traceback (most recent call last):
example_app | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 34, in inner
example_app | response = get_response(request)
example_app | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 145, in _get_response
example_app | response = self.process_exception_by_middleware(e, request)
example_app | File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 143, in _get_response
example_app | response = response.render()
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/response.py", line 105, in render
example_app | self.content = self.rendered_content
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/response.py", line 83, in rendered_content
example_app | return template.render(context, self._request)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
example_app | return self.template.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 171, in render
example_app | return self._render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
example_app | return self.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
example_app | return compiled_parent._render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
example_app | return self.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
example_app | return compiled_parent._render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
example_app | return self.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
example_app | result = block.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
example_app | result = block.nodelist.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 936, in render
example_app | bit = node.render_annotated(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
example_app | return self.render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/base.py", line 33, in render
example_app | return super().render(context)
example_app | File "/usr/local/lib/python3.9/site-packages/django/template/library.py", line 214, in render
example_app | _dict = self.func(*resolved_args, **resolved_kwargs)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 342, in result_list
example_app | 'results': list(results(cl)),
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 318, in results
example_app | yield ResultList(None, items_for_result(cl, res, None))
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 309, in __init__
example_app | super().__init__(*items)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/templatetags/admin_list.py", line 232, in items_for_result
example_app | f, attr, value = lookup_field(field_name, result, cl.model_admin)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 273, in lookup_field
example_app | attr = getattr(obj, name)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/contenttypes/fields.py", line 243, in __get__
example_app | rel_obj = ct.get_object_for_this_type(pk=pk_val)
example_app | File "/usr/local/lib/python3.9/site-packages/django/contrib/contenttypes/models.py", line 175, in get_object_for_this_type
example_app | return self.model_class()._base_manager.using(self._state.db).get(**kwargs)
example_app | AttributeError: 'NoneType' object has no attribute '_base_manager'
I've tried reverting the migration and rerunning it many times. I've also looked at other similar questions but none of the solutions worked or addressed my specific issue.
Why is this happening?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我怀疑添加新字段并不是问题的原因 - 这只是巧合,问题是在您进行此更改的同时出现的。线索就在回溯中:
具体来说,错误来自
contenttypes
框架 - 即,您的content_type
字段在数据库中至少一个现有模型实例上被破坏。model_class ()
方法返回空值而不是模型类。最可能的原因是您删除了之前由通用外键引用的模型,或者您已从
INSTALLED_APPS
中删除了提供该模型的应用。您应该能够通过运行 来解决该问题
remove_stale_contenttypes
管理命令。如果这不起作用,那么可能需要手动检查数据库以找出问题所在(清空整个数据库也将有助于验证这是否是问题所在)。FieldDoesNotExist
异常不是问题。它将被正确处理如果您的内容类型没有问题,则为 Django。旁注:我认为这与您的问题没有任何关系,但使用与 Python 冲突的名称并不是一个好主意 内置函数,因为它可能会导致令人困惑的行为。
I suspect that adding a new field isn't the cause of the problem - it's just coincidence that the problem arose at the same time as you made this change. The clue is in the traceback:
Specifically, the error is coming from the
contenttypes
framework - i.e., yourcontent_type
field is broken on at least one existing model instance in the database. Themodel_class()
method is returning a null value instead of the model class.The most likely cause of this is that you have deleted a model which was previously being referred to by your generic foreign key, or you have removed the app which provided that model from
INSTALLED_APPS
.You should be able to resolve the issue by running the
remove_stale_contenttypes
management command. If that doesn't work, then it's probably going to be a case of manually inspecting the database to find out where the problem is (emptying the whole database will also help verify whether this is the issue).The
FieldDoesNotExist
exception is not a problem. It would be properly handled by Django if there wasn't an issue with your content types.Side note: I don't think it has anything to do with your problem, but it's not a good idea to use names that clash with Python built-in functions as it can lead to confusing behaviour.