我做了一个ModelForm,在模型中添加了一些不的额外字段。保存表单时,我会使用这些字段进行一些计算。
表单上会显示额外字段,上传表单时会在POST请求中发送这些字段。问题是,当我验证表单时,它们没有添加到cleaned_data
字典中。我该如何访问它们?
答案 0 :(得分:21)
可以使用额外字段扩展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
)
...
希望它有所帮助。祝你好运!
编辑:
我得到了一个"只能连接元组(不是" list")到元组" AvatarProfileForm.Meta.fields属性中的错误。将其更改为元组并且有效。
答案 1 :(得分:5)
首先,你不应该有artist_id和artist字段。它们是从模型构建的。如果您需要某个艺术家姓名,请添加artist_name字段,即 CharField 。
此外,您正在尝试从clean_data中清除值中检索某些内容。可能没有您需要的数据 - 您应该使用self.data中的值,其中的数据直接来自POST。
答案 2 :(得分:4)
对于原始海报,这个答案可能为时已晚,但我认为这可能有助于其他人。我有同样的问题,我注意到self.cleaned_data('artist_id')可以在clean()方法中访问,但不能在clean_artist()中访问。
当我在Meta的'fields'声明中添加了额外的字段时,它就有用了。
class Meta:
model = Music
fields=[..., 'artist_id']
您应该能够访问clean_artist()中的self.cleaned_data('artist_id')。
答案 3 :(得分:3)
我有一个非常相似的问题,只是看起来我做了所有必需的事情,但是在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())
这里没有回答眼前的问题(已经得到很好的回答),但可能会帮助其他人。
答案 4 :(得分:2)
好的,我已经解决了。似乎使用cleaning_data ['field_name']访问额外字段会引发KeyError,但使用cleaning_data.get('field_name')可以正常工作。这很奇怪,因为可以通过cleaning_data ['field_name']访问模型的正常字段。
更新:不,它不起作用。使用get()时,它不会引发KeyError,但会将值设置为None,因为额外的字段不在cleaning_data字典中。
这是代码。在模板中有一个自动完成,因此在表单中有一个“artist”字段呈现为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
答案 5 :(得分:1)
首先以表单的形式添加字段
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')
答案 6 :(得分:0)
在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",
)