Django自定义slug生成器用get_model报AppRegistryNotReady如何解决
问题根因
- 你当前的写法是在模型字段定义时直接执行了
slug_generator函数,而非将可调用对象传给default参数:Django加载models.py模块阶段应用注册表尚未初始化完成,此时调用apps.get_model自然触发AppRegistryNotReady错误。 - 额外隐患:直接调用函数生成默认值的话,所有实例的默认slug会是项目启动时生成的同一个固定值,而非每个实例新建时生成独立值,完全不符合功能预期。
解决方案
跨模型通用的slug生成器完全可行,无需为每个模型单独编写硬编码逻辑,按以下步骤修改即可:
步骤1:保留原有slug生成函数逻辑(可做可选优化)
import random import string from django.apps import apps def slug_generator(django_app, django_model, field_name, slug_len, prefix=""): unique_pk = False model = apps.get_model(django_app, django_model) char_pool = string.ascii_uppercase + string.digits + string.ascii_lowercase while not unique_pk: # 用random.choices替代sample,支持超过62位的slug长度需求 random_pks = random.choices(char_pool, k=slug_len) new_pk = ''.join(random_pks) search_query = {field_name: new_pk} if not model.objects.filter(**search_query).exists(): unique_pk = True return prefix + new_pk
步骤2:修改模型字段的default参数写法
使用functools.partial绑定参数,将可调用对象传给default,这样函数只会在每次新建模型实例需要生成默认值时执行,此时应用注册表已经完成初始化,不会触发报错:
from functools import partial from django.db import models class Form(models.Model): form_id = models.CharField( max_length=25, default=partial(slug_generator, 'forms', 'Form', 'form_id', 25) ) # 建议加唯一约束,避免极端竞态条件下生成重复slug class Meta: constraints = [ models.UniqueConstraint(fields=['form_id'], name='unique_form_id') ]
可选优化点
如果需要进一步降低竞态冲突概率,可以在slug生成逻辑中捕获数据库唯一约束异常,遇到重复时自动重试即可。
内容的提问来源于stack exchange,提问作者codego
相关产品推荐
相关产品推荐

