Джанго - ограничить выбор тем, что зависит от конкретного случая - PullRequest
8 голосов
/ 06 октября 2011

У меня есть несколько 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'
    )

(Причина, по которой winner является ManyToManyField, заключается в том, что один foo может принадлежать нескольким категориям, в то время как в одной категории может быть более одного победителя из-за экс-aequo.)

Я хочу наложить естественное ограничение на то, что foo может выиграть в категории, только если он принадлежит этой категории. Наиболее разумный способ сделать это, похоже, использовать параметр limit_choices_to, но мне кажется, что невозможно ограничить выбор на основе текущего экземпляра модели.

Возможно, мне удастся наложить это ограничение в заданной форме, но я бы хотел избежать этого по двум причинам:

  • ограничение естественным образом живет на уровне модели. Это особое отношение, которое всегда должно соблюдаться между двумя родственными моделями
  • выбор победителя будет сделан в админе, и я хотел бы избежать необходимости настраивать формы администратора

Есть ли способ наложить это ограничение на Джанго?

1 Ответ

4 голосов
/ 06 октября 2011

Нет способа наложить ограничение на поле 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()

Ну, вы заметили это?

my_category.category.all()

Возможно, что вы хотите:

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