Как изменить поведение рендеринга полей в зависимости от состояния других полей модели в Django - PullRequest
2 голосов
/ 11 января 2012

Давайте предположим, что у меня есть следующие модели:

class ScoutBook(models.Model):
       troop = models.ForeignKey('Dictionary', limit_choices_to={'type' : 'Troop'},  related_name='+', blank=True, null=True)

class Dictionary(models.Model): 
     name = models.CharField(max_length=CHAR_FIELD_MAX_LEN, verbose_name="Nazwa")
     active = models.BooleanField(verbose_name="Aktywny")
     type = models.CharField(max_length=CHAR_FIELD_MAX_LEN, choices=DICTIONARY_CHOICES)

, и я хочу реализовать следующую логику:

при создании ScoutBook разрешать пользователям выбирать только активные войска, а при редактировании разрешатьвыберите активные войска или разрешите пользователю оставить значение без изменений (даже если отряд неактивен).Если я использую limit_choices_to = {..., 'active' = True} отряд, который неактивен, отсутствует в поле со списком в администраторе django.

Итак, чтобы быть ясным: давайте предположим, что в этой системе четыре войска: Troop1, Troop2 и InactiveTroop, InactiveTroop2.При создании модели я бы хотел, чтобы пользователь мог выбирать Troop1 и Troop2.Если для модели поля войск установлено значение InactiveTroop2, я бы хотел, чтобы пользователь мог выбирать между InactiveTroop2, Troop1 и Troop2.

Я смотрел на API форм django и не нашел очевидного способа сделать это.Более того, в разрабатываемом приложении будет много таких областей и много таких моделей, поэтому решение должно быть безболезненным.Я бы не хотел создавать новый класс Form для каждой модели.Я буду использовать в основном администратор django, чтобы разрешить редактирование базы данных, и некоторые представления только для чтения, которые будут просто перечислять записи.

В идеале я хотел бы инкапсулировать эту функциональность в некоторые настраиваемые поля - но поля имеют доступ к экземпляру модели на этапе проверки и сохранения - поэтому у меня нет доступа к нему при создании поля формы.

Ответы [ 2 ]

0 голосов
/ 14 января 2012

Ну, мне пришлось подключиться к созданию ModelForm.Прикрепленная форма проверяет ее поля и, если выполняются определенные условия, заменяет набор запросов поля модели.

    class DictionayModelForm(ModelForm):
        def __init__(self, *largs, **kwargs):
            super(DictionayModelForm, self).__init__(*largs, **kwargs)
            if self.instance and self.instance.pk is not None:
                for f in self.instance._meta.fields:
                    if isinstance(f, models.ForeignKey) and issubclass(f.rel.to, Dictionary):
                        model_field = self.fields[f.name]
                        value = getattr(self.instance, f.name, None)
                        if value and value not in model_field.choices:
                            model_field.queryset = Dictionary.objects.filter(Q(**f.rel.limit_choices_to) | Q(id = value.id))
0 голосов
/ 11 января 2012

Это звучит как то, что вы хотите сделать в форме, а не в самом объекте.Создайте ModelForm и переопределите ModelChoiceField следующим образом:

from django import forms

class ScoutBookForm(forms.ModelForm):
    troop = forms.ModelChoiceField(queryset=Troop.objects.filter(active=True))
    class Meta:
        model = ScoutBook

Вы также можете переопределить метод clean ScoutBook , чтобы гарантировать, что его невозможно сохранить с помощьюнеактивный отряд, хотя это может иметь некоторые непредвиденные последствия (например, вы не сможете обновить ScoutBook у администратора, если в какой-то момент в прошлом отряд неактивен).

...