根据保存的数据填充Django字段(模型)中的选项

时间:2014-11-10 17:47:05

标签: python django

让我们考虑以下模型

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}}。

你会怎么做?

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)