Как вы динамически обновляете поля класса Meta в Django из конструктора форм? - PullRequest
17 голосов
/ 14 июня 2010

Я хочу обновить Meta.fields динамически.Возможно ли это сделать из конструктора Form?Я попробовал следующее, но year не появляется во время генерации формы.Отображаются только name и title.

class Author(models.Model):
    name = ...
    title = ...
    year = ...

class PartialAuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title')

    def __init__(self, *args, **kwargs):
        self.Meta.fields += ('year',)

Ответы [ 5 ]

17 голосов
/ 14 июня 2010

Нет, это не сработает.Мета-класс анализируется, что удивительно, до того, как вы получите __init__.

. Чтобы сделать это, добавьте поле вручную в self.fields:

def __init__(self, *args, **kwargs):
    super(PartialAuthorForm, self).__init__(*args, **kwargs)
    self.fields['year'] = forms.CharField(whatever)
14 голосов
/ 21 апреля 2013

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

class MyModelForm(ModelForm):
  class Meta:
    model = MyModel
    fields = ['normalField', 'conditionalField', ]

  def __init__(self, *args, **kwargs):

    super(MyModelForm, self).__init__(*args, **kwargs)

    if condition is True:
      del self.fields['conditionalField']

Выполнение этого другим способом может быть довольно сложным, как указано выше, но условное отбрасывание довольно простое. =)

4 голосов
/ 08 мая 2012

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

def my_form_factory:
    class ModifiedAuthorForm(PartialAuthorForm):
        class Meta(PartialAuthorForm.Meta):
            fields = PartialAuthorForm.Meta.fields
            if hasattr(fields, 'append'):
                fields.append('year')
            else:
                fields = fields + ('year',)
return ModifiedAuthorForm

Конечно, если вы хотите быть устойчивым, вам, вероятно, следует проверить, что поле, которое вы добавляете, еще не находится в fields, и вам, вероятно, также следует обработать exclude.

0 голосов
/ 05 ноября 2015

Добавление поля в форму модели путем переопределения метода __init__ формы не будет работать, поскольку поля формы модели инициализируются перед вызовом конструктора формы.Таким образом, вы не получите никаких значений из фактической модели в форму, и ваши значения не будут сохранены в БД после вызова save.

Вам нужно использовать полную красоту python и использовать декоратор классов, как этот;)

def year_decorator(form_class):
    class ModifiedForm(form_class):
        class Meta(form_class.Meta):
            if isinstance(form_class.Meta.model, Author):
                fields = form_class.Meta.fields + ('year',)
    return ModifiedForm


@year_decorator
class PartialAuthorForm(ModelForm):
    class Meta:
         model = Author
         fields = ('name', 'title')
0 голосов
/ 14 июня 2010

Внутренний класс Meta уже обрабатывается, когда класс ModelForm создается с помощью метакласса, то есть ДО создания экземпляра.Выполнение того, что вы пытаетесь сделать в __init__, не будет работать так!
Вы можете получить доступ к созданным объектам поля в диктонарном self.fields, например.Вы можете сделать что-то вроде self.fields['year'] = forms.MyFormField(...).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...