如何在Django模型中根据新增/编辑记录动态设置choices选项
解决Django模型新增/编辑时用不同Choices的问题
嘿,我来给你捋捋这个问题哈~你原来的代码为啥没效果呢?因为你在类定义阶段就去判断test is True,但test是个实例方法啊,这时候连模型实例都还没创建呢,而且直接拿方法对象和True比,结果肯定是False,所以Choices根本不会切换。
给你两种靠谱的解决办法,优先推荐第一种:
方法一:在表单层控制(最稳妥)
模型层的Choices是全局配置,其实更灵活的方式是在表单里根据当前是新增还是编辑状态,动态设置字段的Choices,完全不影响模型本身的存储逻辑。
先写个自定义表单:
from django import forms from .models import MyModel class MyModelForm(forms.ModelForm): class Meta: model = MyModel fields = ['my_field'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 判断是否是编辑状态——实例有pk就说明是已存在的记录 if self.instance.pk: # 编辑时用这组选项 self.fields['my_field'].choices = (('1', 'Option 1'), ('2', 'Option 2'),) else: # 新增时用完整的选项组 self.fields['my_field'].choices = (('1', 'Option 1'), ('2', 'Option 2'), ('3', 'Option 3'), ('4', 'Option 4'),)
然后在视图里用这个表单就行,比如用通用视图的话:
from django.views.generic.edit import CreateView, UpdateView from .models import MyModel from .forms import MyModelForm class MyModelCreateView(CreateView): model = MyModel form_class = MyModelForm success_url = '/success/' # 换成你自己的成功跳转地址 class MyModelUpdateView(UpdateView): model = MyModel form_class = MyModelForm success_url = '/success/'
方法二:模型层动态修改Choices(不推荐,有坑)
如果你非要在模型层处理,也可以重写模型的__init__方法,但要注意这种方式可能在一些场景(比如admin批量操作)出问题,因为admin有时候会绕过实例初始化直接操作模型。
示例代码:
class MyModel(models.Model): # 先把两组选项存成类属性 BASE_CHOICES = (('1', 'Option 1'), ('2', 'Option 2'), ('3', 'Option 3'), ('4', 'Option 4'),) EDIT_CHOICES = (('1', 'Option 1'), ('2', 'Option 2'),) # 先默认用基础选项 my_field = models.CharField(max_length=1, choices=BASE_CHOICES) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 实例有pk就说明是编辑状态,切换Choices if self.pk: self._meta.get_field('my_field').choices = self.EDIT_CHOICES else: self._meta.get_field('my_field').choices = self.BASE_CHOICES
还是要啰嗦一句,模型层的这种方式在Django admin里可能需要额外适配,所以优先选表单层的方案更省心~
内容的提问来源于stack exchange,提问作者Fish
相关产品推荐
相关产品推荐

