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

10 投票
1 回答
3395 浏览
提问于 2025-04-17 03:47

我有一些叫做“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'
    )

这里提到的winnerManyToManyField,是因为一个foo可以属于多个类别,而在一个类别里可能会有多个获胜者(比如并列获胜的情况)。

我想要确保一个foo只有在属于某个类别时,才能在这个类别中获胜。最合理的方法似乎是使用limit_choices_to这个参数,但我觉得不能根据当前模型的实例来限制选择。

我可能可以在某个表单中强制这个限制,但我想避免这样做,原因有两个:

  • 这个限制本质上应该在模型层面上存在。它是两个相关模型之间应该始终保持的特定关系。
  • 获胜者的选择将在管理后台进行,我希望避免定制管理表单。

有没有办法在Django中强制这个限制呢?

1 个回答

6

在模型层面上,无法对多对多字段设置限制(比如使用 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()

你注意到了吗?

my_category.category.all()

你可能想要的是:

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

撰写回答