让我们考虑以下模型
class MyModel(models.Model):
stock = models.IntegerField(blank=True, default=0)
to_be_filled_later = models.CharField(max_length=20, blank=True)
还假设我手动创建了一个条目,stock
设置为42,to_be_filled_later
留空。
当我转到MyModel
的管理面板(修改)并选择我的新条目时,我想将to_be_filled_later
设置为某个值,但我还想限制可能值的集合基于self.stock
的当前值,即 42。
由于Field.choices
可以设置为任何可迭代的,因此可能会尝试执行类似
class MyModel(models.Model):
stock = models.IntegerField(blank=True, default=0)
def restricted_choices(self):
# do something based on self.stock
yield (some_stuff.pk, some_stuff.name)
to_be_filled_later = models.CharField(max_length=20,
blank=True,
choices=restricted_choices(self))
但是这不起作用,因为restricted_choices
应该使用self
的引用来调用,而to_be_filled_later
未在我们创建字段的范围中定义(此处在__init__
的定义中,确切地说。)
我们可以覆盖choices
,但这不是我们想要的,因为它会在每次创建条目后生效。我们想要的是拥有一个动态的,基于实例的 {{1}}。
你会怎么做?
答案 0 :(得分:2)
你做想要覆盖__init__
,但是在表单中,而不是在模型中。
class MyModelForm(forms.ModelForm):
to_be_filled_later = forms.ChoiceField(choices=[])
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
if self.instance:
self.fields['to_be_filled_later'].choices = restricted_choices(self.instance.stock)
并将此表单分配给MyModel的模型管理员:
class MyModelAdmin(admin.ModelAdmin):
model = MyModel
form = MyModelForm
admin.site.register(MyModel, MyModelAdmin)