Django ModelForm с дополнительными полями, не входящими в модель
Я сделал ModelForm, добавив несколько дополнительных полей, которые не являются в модели. Я использую эти поля для некоторых вычислений при сохранении формы.
Дополнительные поля появляются в форме, и они отправляются в запрос POST при загрузке формы. Проблема в том, что они не добавляются в словарь cleaned_data
, когда я проверяю форму. Как я могу получить к ним доступ?
Ответы
Ответ 1
Возможно расширение Django ModelForm
с дополнительными полями. Представьте, что у вас есть пользовательская модель пользователя и ModelForm
:
class ProfileForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'country', 'website', 'biography']
Теперь представьте, что вы хотите включить дополнительное поле (не присутствующее в вашей модели пользователя, скажем, аватар изображения). Расширьте свою форму, выполнив следующие действия:
from django import forms
class AvatarProfileForm(ProfileForm):
profile_avatar = forms.ImageField()
class Meta(ProfileForm.Meta):
fields = ProfileForm.Meta.fields + ('profile_avatar',)
Наконец (учитывая, что форма имеет ImageField
), не забудьте включить request.FILES
при создании формы в вашем представлении:
# (view.py)
def edit_profile(request):
...
form = AvatarProfileForm(
request.POST or None,
request.FILES or None,
instance=request.user
)
...
Надеюсь, это поможет. Удачи!
ИЗМЕНИТЬ:
Я получал "can only concatenate tuple (not" list "), чтобы закодировать" ошибку в атрибуте AvatarProfileForm.Meta.fields ". Изменил его на кортеж, и он сработал.
Ответ 2
Во-первых, у вас не должно быть полей artist_id и artist. Они построены из модели. Если вам нужно имя исполнителя, добавьте имя_имя_имя, то есть CharField.
Кроме того, вы пытаетесь извлечь что-то из cleaned_data внутри чистого значения. Возможно, вам не нужны данные - вы должны использовать значения из self.data, где находятся данные непосредственно из POST.
Ответ 3
Этот ответ может быть слишком поздним для оригинального плаката, но я думал, что это может помочь другим. У меня была та же проблема, и я заметил, что self.cleaned_data ('artist_id') можно получить в методе clean(), но не в clean_artist().
Когда я добавил дополнительные поля в декларацию 'fields' в Meta, тогда это сработало.
class Meta:
model = Music
fields=[..., 'artist_id']
Вы должны иметь доступ к self.cleaned_data ('artist_id') в clean_artist().
Ответ 4
Хорошо, я решил. Кажется, что доступ к дополнительным полям с cleaned_data ['field_name'] вызывает KeyError, но используется cleaned_data.get('field_name'). Это странно, потому что обычные поля для модели можно получить через cleaned_data ['field_name'].
Обновление: Нет, это не сработает. С get() он не вызывает KeyError, но устанавливает значение None, потому что дополнительные поля не находятся в словаре cleaned_data.
Вот код. В шаблонах есть автозаполнение, поэтому в форме есть поле "художник", отображаемое как CharField и скрытый IntegerField, который будет автопопулен с данным идентификатором исполнителя. В методе clean_artist я хочу выбрать объект художника и сохранить его в поле исполнителя формы.
models.py
class Music(models.Model):
artist = models.ForeignKey(Artist, related_name='music', blank=True, null=True)
# other fields...
forms.py
class MusicForm(forms.ModelForm):
artist_id = forms.IntegerField(label="", widget=forms.HiddenInput(), required=False)
artist = forms.CharField(required=False)
# other fields ...
class Meta:
model = Music
def clean_artist(self):
if self.cleaned_data.get('artist') == '':
artist = None
else:
artist_id = self.cleaned_data.get('artist_id') # this returns always None because artist_id is not in cleaned_fields (this seemed to work with previous django versions but not with current SVN version)
if artist_id != None:
artist = Artist.objects.get(id=artist_id)
else:
artist = None
return artist
Ответ 5
У меня была очень похожая проблема, за исключением того, что казалось, что я сделал все необходимое, но я получал эту ошибку, когда запускался Django:
django.core.exceptions.FieldError: Unknown field(s) (my_new_field) specified for MyModel
Это была моя глупая ошибка, я случайно объявил свое поле с помощью класса Widget:
class MyForm(forms.ModelForm):
my_new_field = forms.HiddenInput()
Вместо класса Field:
class MyForm(forms.ModelForm):
my_new_field = forms.CharField(widget=forms.HiddenInput())
Не отвечая на данный вопрос (на который уже дан хороший ответ), но может помочь другим.
Ответ 6
Сначала добавьте поле в форму
class CreateForm(forms.ModelForm):
extra_field = forms.CharField(label = 'extra_field', required = False)
Теперь при очистке данных вам нужно извлечь дополнительное поле из self.data, а не self.cleaned_data.
Исправить:
self.data.get('extra_field')
Неправильно
self.cleaned_data.get('extra_field')