Ответ 1
fields
не существует до после, который вы вызывали super
. Поэтому просто поменяйте порядок строк, чтобы super
появился первым.
При создании плоской страницы я хочу, чтобы пользователь выбирал шаблон из предопределенного списка. Чтобы сохранить модель Flatpage
нетронутой, я предпочитаю ChoiceField
над ModelChoiceField
(последний предоставляет PK шаблона, но мне нужно имя для поля template_name):
class NewFlatpageForm(FlatpageForm):
template_name = forms.ChoiceField(choices = [])
def __init__(self, *args, **kwargs):
self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name')
super(NewFlatpageForm, self).__init__(*args, **kwargs)
Я переопределяю __init__
или Django заполняет варианты при запуске сервера и не обновляет список.
У меня нет никакого администрирования, но я делал подобные вещи, используя атрибут fields
, когда не использовал admin. Однако в этом случае я получил исключение, говорящее, что fields
не является атрибутом формы. __dict__
показал мне атрибут base_fields
, и его использование работает. Итак, зачем использовать base_fields здесь, и почему fields
нет, и, наконец, я делаю что-то взломанное?
fields
не существует до после, который вы вызывали super
. Поэтому просто поменяйте порядок строк, чтобы super
появился первым.
Урок по собственному опыту: изменение базовых полей означает, что ваши модификации придерживаются "навсегда" (до выхода python). В вашем случае это, вероятно, не проблема, поскольку вы всегда используете одно и то же имя поля, и вы заменяете его значения назначением из ProjectTemplate...
В моем случае я хотел получить совершенно разные поля на основе параметров в конструкторе. Поскольку имена полей обычно отличались друг от друга, каждый раз, когда я создавал форму, я добавлял новые поля, но не удалял их из последнего раза.
Вызывая супер ранний (как указано здесь), а затем делая мои динамические изменения в self.fields вместо self.basefields, я смог устранить проблему постоянно растущего списка полей. Теперь это имеет прекрасный смысл, но я не был знаком со всеми деталями синтаксиса и взломал вместо того, чтобы сначала понять его.
В дополнение к Джо Гермушке. Если вам действительно нужно изменить форму на основе запроса, вы можете использовать глубокую копию, чтобы убедиться, что ничто не изменяется по ссылке:
def get_form(self, request, obj=None, **kwargs):
form = super(ResourceAdmin, self).get_form(request, obj, **kwargs)
form = copy.deepcopy(form)
if obj:
form.base_fields['email'] = EmailField(initial=obj.user.email)
if not request.user.is_superuser:
form.base_fields['user'].widget = HiddenInput(attrs={'class': 'hide_form_row'})
return form