Как вы динамически обновляете поля класса Django Form Meta из конструктора формы?
Я хочу динамически обновлять Meta.fields
. Можно ли это сделать из конструктора формы? Я попробовал следующее, но 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',)
Ответы
Ответ 1
Нет, это не сработает. Мета анализируется - удивительно - метаклассом, прежде чем вы даже дойдете до __init__
.
Способ сделать это - добавить поле вручную в self.fields
:
def __init__(self, *args, **kwargs):
super(PartialAuthorForm, self).__init__(*args, **kwargs)
self.fields['year'] = forms.CharField(whatever)
Ответ 2
Ответы других - великие (особенно @BranHandleys), но иногда их проще всего условно удалить что-то. Очевидно, что это не работает с вещами, которые динамически создаются, но если вам нужно только указать поле или нет, тогда попробуйте сделать это следующим образом.
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']
Выполнение этого по-другому может быть довольно сложным, как указано выше, но условно отбросить его довольно просто. =)
Ответ 3
Ответы на использование __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
.
Ответ 4
Внутренний класс Meta
уже обрабатывается, когда класс ModelForm создается через метакласс, который до того, как создается экземпляр. Выполнение того, что вы пытаетесь сделать в __init__
, не будет работать так!
Вы можете получить доступ к созданным объектам поля в справочнике self.fields
например. вы можете сделать что-то вроде self.fields['year'] = forms.MyFormField(...)
.
Ответ 5
Добавление поля в форму модели путем переопределения формы __init__ метод не будет работать, поскольку поля формы модели инициализируются перед вызовом конструктора формы. Таким образом, вы не получите никаких значений от фактической модели до формы, и ваши значения не будут сохранены в db после сохранения вызова.
Вам нужно использовать полную красоту 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')