我们假设我有以下模型:
class ScoutBook(models.Model):
troop = models.ForeignKey('Dictionary', limit_choices_to={'type' : 'Troop'}, related_name='+', blank=True, null=True)
class Dictionary(models.Model):
name = models.CharField(max_length=CHAR_FIELD_MAX_LEN, verbose_name="Nazwa")
active = models.BooleanField(verbose_name="Aktywny")
type = models.CharField(max_length=CHAR_FIELD_MAX_LEN, choices=DICTIONARY_CHOICES)
我想实现以下逻辑:
创建ScoutBook时,允许用户只选择活动部队,编辑时允许选择活动部队或允许用户保持值不变(即使部队处于非活动状态)。如果我使用limit_choices_to = {..., 'active' = True}
django admin中的组合框中没有非活动队伍。
所以要明确:让我们假设这个系统中有四个部队:Troop1
,Troop2
和InactiveTroop
,InactiveTroop2
。在模型创建方面,我希望用户能够选择Troop1
和Troop2
。如果模型的部队字段设置为InactiveTroop2
,我希望用户能够在InactiveTroop2
,Troop1
和Troop2
之间进行选择。
我正在看django表格api,我没有找到明显的办法。而且,在我正在开发的应用程序中,将会有许多这样的领域和许多这样的模型---因此解决方案必须是无痛的。我宁愿不为每个模型创建新的Form类。我将主要使用django admin来启用编辑数据库,以及一些只读列表条目的只读视图。
理想情况下,我想在一些自定义字段中封装此功能---但是字段可以在验证和保存阶段访问模型实例---所以当我生成formfield时我无法访问它。
答案 0 :(得分:0)
这听起来像你想要在表单中做的事情,而不是在对象本身。创建一个ModelForm并覆盖ModelChoiceField,如下所示:
from django import forms
class ScoutBookForm(forms.ModelForm):
troop = forms.ModelChoiceField(queryset=Troop.objects.filter(active=True))
class Meta:
model = ScoutBook
您还可以override the clean
method of ScoutBook确保无法使用非活动队伍保存它,但这可能会产生一些意想不到的后果(例如,如果部队拥有,您将无法在管理员中更新ScoutBook在过去的某个时刻变得不活跃。)
答案 1 :(得分:0)
好吧,我不得不挂钩进入ModelForm创建。附加表单检查它的字段,如果满足特定条件,它将替换模型字段查询集。
class DictionayModelForm(ModelForm):
def __init__(self, *largs, **kwargs):
super(DictionayModelForm, self).__init__(*largs, **kwargs)
if self.instance and self.instance.pk is not None:
for f in self.instance._meta.fields:
if isinstance(f, models.ForeignKey) and issubclass(f.rel.to, Dictionary):
model_field = self.fields[f.name]
value = getattr(self.instance, f.name, None)
if value and value not in model_field.choices:
model_field.queryset = Dictionary.objects.filter(Q(**f.rel.limit_choices_to) | Q(id = value.id))