簡體   English   中英

帶有不在模型中的額外字段的 Django ModelForm

[英]Django ModelForm with extra fields that are not in the model

我做了一個 ModelForm,添加了一些模型中沒有的額外字段。 保存表單時,我將這些字段用於一些計算。

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

可以使用額外的字段擴展 Django ModelForm 想象一下你有一個自定義的 User 模型和這個ModelForm

class ProfileForm(forms.ModelForm):

    class Meta:
        model = User
        fields = ['username', 'country', 'website', 'biography']

現在,假設您想要包含一個額外的字段(不存在於您的 User 模型中,例如圖像頭像)。 通過執行以下操作擴展您的表單:

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 屬性中收到“只能將元組(不是“列表”)連接到元組”錯誤。 將其更改為元組並且它起作用了。

我有一個非常相似的問題,只是看起來我做了所有必需的事情,但是當 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())

不在這里回答手頭的問題(已經回答得很好),但可能會幫助其他人。

首先在表單中添加字段

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

首先,你不應該有artist_id 和artist 字段。 它們是從模型構建的。 如果您需要一些藝術家姓名,請添加 Artist_name 字段,即CharField

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

這個答案對於原始海報來說可能為時已晚,但我認為它可能對其他人有所幫助。 我遇到了同樣的問題,我確實注意到 self.cleaned_data('artist_id') 可以在 clean() 方法中訪問,但不能在 clean_artist() 中訪問。

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

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

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

好的,我已經解決了。 似乎使用cleaned_data['field_name'] 訪問額外的字段會引發KeyError 但使用cleaned_data.get('field_name') 有效。 這很奇怪,因為模型的普通字段可以通過cleaned_data['field_name'] 訪問。

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

這是代碼。 在模板中有一個自動完成功能,因此在表單中有一個呈現為 CharField 的“藝術家”字段和一個隱藏的 IntegerField,它將使用給定的藝術家 ID 自動填充。 在 clean_artist 方法中,我想選擇藝術家對象並將其存儲在表單的藝術家字段中。

模型.py

class Music(models.Model):
    artist = models.ForeignKey(Artist, related_name='music', blank=True, null=True)
    # other fields...

表格.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

在 Django 2 中,您可以添加字段,因為它是一個普通表單

class CreateCompanyForm(forms.ModelForm):

    password_confirmation = forms.CharField(
        label=translate('Password confirmation'),
        max_length=70,
        widget=forms.PasswordInput(),
        required=True,
    )
    company_name = forms.CharField(
        label="Nombre de la Compañía",
        max_length=90,
        widget=forms.TextInput(),
        required=True,
    )

    class Meta:
        model = AppUser
        fields = (
            "email",
            "first_name",
            "last_name",
            "password",
        )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM