Подтвердить что ты не робот

Django ModelForm с дополнительными полями, не входящими в модель

Я сделал ModelForm, добавив несколько дополнительных полей, которые не являются в модели. Я использую эти поля для некоторых вычислений при сохранении формы.

Дополнительные поля появляются в форме, и они отправляются в запрос POST при загрузке формы. Проблема в том, что они не добавляются в словарь cleaned_data, когда я проверяю форму. Как я могу получить к ним доступ?

4b9b3361

Ответ 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')