You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:12:43