Django ModelForm с дополнительными полями, которых нет в модели - PullRequest
33 голосов
/ 09 февраля 2010

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

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

Ответы [ 6 ]

22 голосов
/ 29 апреля 2014

Возможно расширение 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
    )
    ...

Надеюсь, это поможет. Удачи!

РЕДАКТИРОВАТЬ:

В атрибуте AvatarProfileForm.Meta.fields я получаю сообщение об ошибке «можно объединить только кортеж (не« список ») и кортеж»). Изменил его на кортеж, и это сработало.

5 голосов
/ 09 февраля 2010

Во-первых, у вас не должно быть полей artist_id и artist. Они построены по модели. Если вам нужно указать имя исполнителя, добавьте поле artist_name, то есть CharField .

Кроме того, вы пытаетесь получить что-то из cleaned_data внутри чистого значения. Возможно, вам не нужны данные - вы должны использовать значения из self.data, где есть данные непосредственно из POST.

4 голосов
/ 01 апреля 2015

Этот ответ может быть слишком поздно для оригинального плаката, но я подумал, что он может помочь другим. У меня была та же проблема, и я заметил, что self.cleaned_data ('artist_id') можно получить в методе clean (), но не в clean_artist ().

Когда я добавил дополнительные поля в объявлении Meta 'fields', это сработало.

    class Meta:
        model = Music
        fields=[..., 'artist_id']

Вы должны иметь доступ к self.cleaned_data ('artist_id') в clean_artist ().

3 голосов
/ 04 октября 2018

У меня была очень похожая проблема, за исключением того, что выглядело так, как будто я сделал все необходимое, но я получал эту ошибку при запуске Django:

django.core.exceptions.FieldError: Unknown field(s) (my_new_field) specified for MyModel

Это была моя глупая ошибка, я случайно объявил свое поле, используя Widget class:

class MyForm(forms.ModelForm):
    my_new_field = forms.HiddenInput()

Вместо Поле Класс:

class MyForm(forms.ModelForm):
    my_new_field = forms.CharField(widget=forms.HiddenInput())

Не отвечает на рассматриваемый здесь вопрос (на который уже дан хороший ответ), но может помочь другим.

2 голосов
/ 09 февраля 2010

Хорошо, я решил это. Кажется, что доступ к дополнительным полям с помощью cleaned_data ['field_name'] вызывает KeyError, но использование cleaned_data.get ('field_name') работает. Это странно, потому что к нормальным полям модели можно получить доступ через cleaned_data ['field_name'].

Обновление: Нет, это не работает. С get () он не вызывает KeyError, но устанавливает значение None, потому что дополнительные поля отсутствуют в словаре cleaned_data.

Вот код. В шаблонах есть автозаполнение, поэтому в форме есть поле «Artist», отображаемое как CharField, и скрытое IntegerField, которое будет автоматически заполнено указанным идентификатором Artist. В методе clean_artist я хочу выбрать объект Artist и сохранить его в поле 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
1 голос
/ 17 декабря 2018

Сначала добавьте поле в форму

class CreateForm(forms.ModelForm):

extra_field     = forms.CharField(label = 'extra_field', required = False)

Теперь при очистке данных вам нужно извлечь дополнительное поле из self.data NOT self.cleaned_data

Корректное

 self.data.get('extra_field')

Неправильный

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