首次尝试Django 2.0模型执行migrations时触发AttributeError
解决Django 2.0模型迁移与Admin注册的AttributeError问题
问题根源
你的错误完全来自admin.py里错误的模型注册方式!admin.site.register()的正确用法是一次注册一个模型,第二个参数是可选的自定义ModelAdmin类(用来定制后台展示),而你把两个模型放在同一个register调用里:
admin.site.register(Author, Book)
这相当于告诉Django:用Book这个模型类作为Author的后台管理类,但Book并不是ModelAdmin的子类,Django尝试访问它的model属性时自然会抛出AttributeError: 'Book' object has no attribute 'model'。
修正Admin注册代码
把每个模型单独注册,修改后的admin.py应该是这样:
from django.contrib import admin from .models import (Author, Book, Narrator, Audiobook) # 每个模型单独调用register方法 admin.site.register(Author) admin.site.register(Book) admin.site.register(Narrator) admin.site.register(Audiobook)
如果之后需要给某个模型定制后台展示(比如显示特定字段),再添加自定义ModelAdmin类,比如给Book加后台展示:
class BookAdmin(admin.ModelAdmin): # 后台列表显示的字段 list_display = ('title', 'list_authors', 'finished') # 注册时传入自定义的ModelAdmin admin.site.register(Book, BookAdmin)
解决后续迁移/URL错误
你提到注释注册代码后迁移成功但后续报'urls'属性错误,这是因为之前错误的注册导致Django的Admin站点初始化异常,残留了错误状态。现在按以下步骤操作:
- 检查你的
migrations目录,删除任何因错误操作生成的多余迁移文件(保留最初的正确迁移,比如0001_initial.py) - 重新执行迁移命令:
python manage.py makemigrations python manage.py migrate - 启动服务后访问Admin后台,应该就能正常运行了。
额外建议:模型继承的注意点
你的Audiobook继承自Book,Django默认是多表继承(即Audiobook会生成一张单独的表,同时关联Book表)。如果你的业务需求是让Audiobook作为Book的子类,共用同一张表(单表继承),需要给Book添加abstract = True的Meta类:
class Book(models.Model): title = models.CharField(max_length=150) description = models.TextField(blank=True, null=True) series = models.CharField(max_length=150, blank=True, null=True) authors = models.ManyToManyField(Author, blank=True) finished = models.BooleanField(default=False, verbose_name="Finished") class Meta: abstract = True # 标记为抽象模型,不会生成单独的表
根据你的实际业务场景选择即可。
内容的提问来源于stack exchange,提问作者Derrick
相关产品推荐
相关产品推荐

