Django ModelForm带有不在模型中的额外字段

问题描述:

我已经完成了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

好的我已经解决了。看起来,使用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

首先,你不应该有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

可以用额外的字段扩展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

这个答案对原始海报来说可能太晚了,但我认为这可能对别人有帮助。我有同样的问题,我注意到可以在clean()方法中访问self.cleaned_data('artist_id'),但不能在clean_artist()中访问。

当我在Meta的'fields'声明中添加额外的字段时,它就起作用了。

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

您应该可以访问clean_artist()中的self.cleaned_data('artist_id')。