执行migrate触发AttributeError:CategoryModel无CATEGORY_CHOICES属性的解决
错误修复方案
问题原因
通过apps.get_model()获取的模型是Django迁移系统生成的历史代理模型,它仅保留与数据库结构相关的字段信息,不会包含你在原模型类上定义的自定义类属性CATEGORY_CHOICES,因此触发AttributeError。
修复方法
方法1:在迁移文件内直接定义CATEGORY_CHOICES
把原模型里的CATEGORY_CHOICES复制到迁移文件的populate_categories函数上方,无需从模型中读取:
def populate_categories(apps, schema_editor): CategoryModel = apps.get_model('app_l3', 'CategoryModel') # 直接在迁移内定义选项 CATEGORY_CHOICES = ( ('hardware', 'Hardware'), ('software', 'Software'), ('network', 'Network'), ('printer', 'Printer'), ('phone', 'Phone'), ('laptop', 'Laptop'), ) for name, desc in CATEGORY_CHOICES: # 用get_or_create避免重复创建数据 CategoryModel.objects.get_or_create(category_name=name, defaults={'description': desc})
方法2:直接导入原始模型类(不推荐,仅限临时场景)
如果一定要从原模型读取选项,可以直接导入,但这种方式会破坏迁移的独立性——后续原模型的CATEGORY_CHOICES被修改时,旧迁移执行可能出错:
from app_l3.models import CategoryModel def populate_categories(apps, schema_editor): for name, desc in CategoryModel.CATEGORY_CHOICES: CategoryModel.objects.get_or_create(category_name=name, defaults={'description': desc})
其他预定义数据填充方法
1. Django Fixtures
创建JSON/YAML格式的fixture文件(比如app_l3/fixtures/categories.json):
[ { "model": "app_l3.categorymodel", "pk": "hardware", "fields": { "description": "Hardware", "category_creation_date": "2024-01-01T00:00:00Z" } }, { "model": "app_l3.categorymodel", "pk": "software", "fields": { "description": "Software", "category_creation_date": "2024-01-01T00:00:00Z" } } ]
执行命令加载数据:
py manage.py loaddata categories.json
2. 使用post_migrate信号
在app_l3/signals.py中定义信号处理函数,每次迁移完成后自动填充:
from django.db.models.signals import post_migrate from django.dispatch import receiver from .models import CategoryModel @receiver(post_migrate) def populate_categories(sender, **kwargs): if sender.name == 'app_l3': for name, desc in CategoryModel.CATEGORY_CHOICES: CategoryModel.objects.get_or_create(category_name=name, defaults={'description': desc})
在app_l3/apps.py中注册信号:
from django.apps import AppConfig class AppL3Config(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'app_l3' def ready(self): import app_l3.signals
3. 第三方库辅助
- django-seed:快速生成批量测试数据,支持按模型规则填充
- factory_boy:编写数据工厂,灵活生成符合业务逻辑的初始数据
4. 自定义管理命令
创建自定义管理命令,手动执行填充:
在app_l3/management/commands/populate_categories.py中编写:
from django.core.management.base import BaseCommand from app_l3.models import CategoryModel class Command(BaseCommand): help = 'Populate category data' def handle(self, *args, **options): for name, desc in CategoryModel.CATEGORY_CHOICES: CategoryModel.objects.get_or_create(category_name=name, defaults={'description': desc}) self.stdout.write(self.style.SUCCESS('Successfully populated categories'))
执行命令:
py manage.py populate_categories
内容的提问来源于stack exchange,提问作者Acno_Sama
相关产品推荐
相关产品推荐

