2010-02-09 5 views
21

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

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

+0

Их следует добавить к словарной записи cleaned_data. Пожалуйста, напишите свой код формы, чтобы мы могли посмотреть. – gruszczy

+0

Я советую вам не хранить информацию в поле «Форма». Более чистое решение: хранить его в сеансах. – sergzach

+0

Если код, который вы опубликовали в вашем последующем ответе, является точной копией и вставкой, тогда есть проблема с отступом в последней строке - он должен быть на одном уровне. –

ответ

1

Хорошо, я разрешил это. Кажется, что доступ к дополнительным полям с 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 
+0

Это странно, потому что get is no отличается от []. Отправьте свой код, и будет легче найти основную проблему. – gruszczy

+4

Обратный художник нуждается в дополнительном отступ. это не в методе clean_artist. –

+1

сделал отступ, исправить проблему? – Anentropic

5

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

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

+0

на самом деле правильно использовать cleaned_data внутри отдельных методов clean_X: http://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-a-specific-field-attribute – Anentropic

+0

Спасибо за издание, @Martin – Cartucho

11

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

Надеется, что это помогает. Удачи!

EDIT:

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

+2

Я получаю 'django.core.exceptions.FieldError: Неизвестные поля (my_new_field), указанные для MyModel', когда я добавляю' my_new_field' в список 'fields'. Django 1.10 – CpILL

4

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

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

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

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

Смежные вопросы