Django - 限制选择依赖于实例的东西

And*_*rea 8 python django django-models django-admin

我有一些组织成类别的foos.对于每个类别,我希望能够选择一个胜利者foo.

因此我的模型看起来像这样:

class Category(models.Model):
    name = models.CharField(max_length=30)
    # More fields...
    winner = models.ManyToManyField(
        'Foo',
        related_name='winner'
    )

class Foo(models.Model):
    name = models.CharField(max_length=30)
    # More fields...
    category = models.ForeignKey(
        Category,
        related_name='category'
    )
Run Code Online (Sandbox Code Playgroud)

(原因winner是a ManyToManyFieldfoo可能属于多个类别,而在单个类别中,由于ex-aequo,可能会有多个获胜者.)

我想强加一个foo可以在类别中获胜的自然约束,只要它属于该类别.最合理的方法似乎是使用limit_choices_to参数,但在我看来,不可能根据模型的当前实例限制选择.

我可能能够以给定的形式强加这种约束,但我想避免这种情况有两个原因:

  • 约束自然生活在模型层面.它应该始终存在于两个相关模型之间
  • 获胜者的选择将在管理员中进行,我希望避免必须自定义管理员表单

有没有办法在Django中强加这个约束?

Mar*_*rat 6

无法在模型级别对 M2M 字段施加约束(即使用 limit_choices_to)。但是,您可以通过以下形式执行此操作:

class MyForm(forms.ModelForm):
    class Meta:
        model = models.Category

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        if 'instance' in kwargs:
            my_category = kwargs['instance']
            self.fields['winner'].queryset = my_category.category.all()
Run Code Online (Sandbox Code Playgroud)

嗯,你注意到了吗?

my_category.category.all()
Run Code Online (Sandbox Code Playgroud)

也许你想要的是:

class Foo(models.Model):
    name = models.CharField(max_length=30)
    # More fields...
    category = models.ForeignKey(
        Category,
        related_name='participants'
    )
Run Code Online (Sandbox Code Playgroud)