2010-02-09 68 views
21

我已經完成了ModelForm,在模型中添加了一些不是的額外字段。保存表單時,我使用這些字段進行一些計算。Django ModelForm帶有不在模型中的額外字段

額外的字段出現在表單上,​​並在上傳表單時在POST請求中發送。問題是我在驗證表單時沒有將它們添加到cleaned_data字典中。我如何訪問它們?

+0

應將它們添加到cleared_data字典中。請張貼您的表格代碼,以便我們可以看一看。 – gruszczy 2010-02-09 12:55:01

+0

我建議你不要在Form域中存儲信息。更清晰的解決方案是:將其存儲在會話中。 – sergzach 2012-05-22 10:32:28

+0

如果您在後續答案中發佈的代碼是精確的複製粘貼,那麼最後一行有一個縮進問題 - 它應該是一級。 – 2010-02-09 16:27:24

回答

1

好的我已經解決了。看起來,使用cleared_data ['field_name']訪問額外的字段引發了一個KeyError,但使用的清潔數據.get('field_name')的作品。這很奇怪,因爲模型的正常字段可以通過cleared_data ['field_name']來訪問。

更新:不,它不起作用。使用get()它不會引發KeyError,但它將值設置爲None,因爲額外的字段不在clean_data字典中。

這是代碼。在模板中有一個自動完成,所以在表單中有一個呈現爲CharField的「藝術家」字段和一個隱藏的IntegerField,將使用給定的藝術家ID進行自動填充。在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不是不同於 []。發佈你的代碼,它會更容易找到潛在的問題。 – gruszczy 2010-02-09 13:48:57

+4

回報藝術家需要額外的縮進。它不在clean_artist方法中。 – 2010-02-09 16:34:43

+1

做了縮進修復問題? – Anentropic 2011-04-21 15:23:19

5

首先,你不應該有artist_id和藝術家領域。它們是從模型構建的。如果您需要某個藝術家名稱,請添加artist_name字段,即CharField

此外,您正嘗試從clean_data內部清除值中檢索某些內容。可能沒有您需要的數據 - 您應該使用self.data中的值,其中數據直接來自POST。

+0

實際上,在單獨的clean_X方法中使用cleared_data是正確的:http://docs.djangoproject.com/zh/dev/ref/forms/validation/#cleaning-a-specific-field-attribute – Anentropic 2011-04-21 15:22:41

+0

感謝版,@Martin – Cartucho 2017-12-20 12:57:09

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 
    ) 
    ... 

希望它能幫助。祝你好運!

編輯:

我得到一個「只能串聯元組(沒有‘名單’),以元組」錯誤AvatarProfileForm.Meta.fields屬性。將它更改爲一個元組,它工作。

+2

當我將'my_new_field'添加到'fields'列表時,我得到'django.core.exceptions.FieldError:爲MyModel指定的未知字段(my_new_field)。 Django 1.10 – CpILL 2017-01-31 02:21:19

4

這個答案對原始海報來說可能太晚了,但我認爲這可能對別人有幫助。我有同樣的問題,我注意到可以在clean()方法中訪問self.cleaned_data('artist_id'),但不能在clean_artist()中訪問。

當我在Meta的'fields'聲明中添加額外的字段時,它就起作用了。

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

您應該可以訪問clean_artist()中的self.cleaned_data('artist_id')。

相關問題