用django形式保存新的外键 [英] Save new foreign key with django form

查看:152
本文介绍了用django形式保存新的外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个模型:

  class Studio(models.Model):
name = models.CharField Studio,max_length = 30,unique = True)

class Film(models.Model):
studio = models.ForeignKey(Studio,verbose_name =Studio)
name = models.CharField(Film Name,max_length = 30,unique = True)

一个电影表单,允许用户选择一个预先存在的工作室,或输入一个新的:

  class FilmForm(forms。表单)
studio = forms.ModelChoiceField(Studio.objects,required = False)
new_studio = forms.CharField(max_length = 30,required = False,label =New Studio Name)
name = forms.CharField(max_length = 30,label =电影名称)

确保new_studio名称不存在。如果用户输入new_studio,我想保存工作室,然后保存新的电影。

  form = FilmForm(request.POST)
如果form.is_valid():#所有验证规则通过
std = Studio(name = form.cleaned_data ['new_studio'])
std.save()

但那么如何保存电影实例受制于全新的工作室标识?我已经看到这个问题,但是如果我在电影模型中有更多的领域,电影表格?如果我使用链接的答案,我必须输入每个字段:

  studio = Studio.objects.get(name = request .POST ['new_studio'])
newFilm = Film(name = form.name,studio = studio,field_one = form.field_one,field_two = form.field_two等)

实现这一点的正确方法是什么?

解决方案>

真的,您唯一的问题是您使用了标准的表单而不是 ModelForm 表单没有保存方法,因为它并不固有地绑定到任何东西(即它不知道什么保存或保存到哪里)



但是,如果您使用 ModelForm ,则需要照顾所有在形式上创建一个新的工作室的逻辑。这实际上是更好的,因为那样你就可以使用表单,而不用担心别的东西:表单包含正确保存自己所需的所有逻辑。

  class FilmForm(forms.ModelForm):
class Meta:
model = Film

#只需要定义`new_studio`,其他字段来自动从模型
new_studio = forms.CharField(max_length = 30,required = False,label =New Studio Name)

def __init __(self,* args,** kwargs)
super(FilmForm,self).__ init __(* args,** kwargs)
#make`studio`不需要,我们将检查`studio`或`new_studio`中的`clean `方法
self.fields ['studio']。required = False

def clean(self):
studio = self.cleaned_data.get('studio')
new_studio = self.cleaned_data.get('new_studio')
如果不是studio而不是new_studio:
#没有指定这样引用对于用户
raise forms.ValidationError('必须指定Studio或New Studio!')的错误
elif not studio:
#从`new_studio`创建`Studio`并使用它为`studio`字段
studio,created = Studio.objects.get_or_create(name = new_studio)
self.cleaned_data ['studio'] = studio

return super(FilmForm ,self).clean()

然后,在你看来,你需要的是:

  if form.is_valid():
form.save()
pre>

I have two models:

class Studio(models.Model):
    name = models.CharField("Studio", max_length=30, unique=True)

class Film(models.Model):
    studio = models.ForeignKey(Studio, verbose_name="Studio")
    name = models.CharField("Film Name", max_length=30, unique=True)

I have a Film form that allows the user to either select a preexisting Studio, or type in a new one:

class FilmForm(forms.Form):
    studio = forms.ModelChoiceField(Studio.objects, required=False)
    new_studio = forms.CharField(max_length=30, required=False, label = "New Studio Name")
    name = forms.CharField(max_length=30, label = "Film Name")

There's validation to assure that the new_studio name doesn't already exist. If the user enters a new_studio, I want to save the studio and then save the new Film.

form = FilmForm(request.POST) 
if form.is_valid(): # All validation rules pass
    std = Studio(name = form.cleaned_data['new_studio'])
    std.save()

But then how do I save the Film instance subject to the brand new studio id? I've seen this question, but what if I have many more fields in the Film model and Film Form? If I use the linked answer, I would have to enter each field:

studio = Studio.objects.get(name=request.POST['new_studio'])
newFilm=Film(name=form.name, studio=studio, field_one = form.field_one, field_two = form.field_two, etc.)

What is the correct way to implement this?

解决方案

Really, your only problem is that you've used a standard Form instead of a ModelForm. Form doesn't have a save method because it's not inherently tied to anything (i.e. it doesn't know what to save or where to save to).

However, if you use a ModelForm you need to take care of all logic involved in creating a new studio in the form. This is actually better, though, because then you can just use the form and not worry about anything else: the form holds all the logic needed to properly save itself.

class FilmForm(forms.ModelForm):
    class Meta:
        model = Film

    # only need to define `new_studio`, other fields come automatically from model
    new_studio = forms.CharField(max_length=30, required=False, label = "New Studio Name")

    def __init__(self, *args, **kwargs):
        super(FilmForm, self).__init__(*args, **kwargs)
        # make `studio` not required, we'll check for one of `studio` or `new_studio` in the `clean` method
        self.fields['studio'].required = False

    def clean(self):
        studio = self.cleaned_data.get('studio')
        new_studio = self.cleaned_data.get('new_studio')
        if not studio and not new_studio:
            # neither was specified so raise an error to user
            raise forms.ValidationError('Must specify either Studio or New Studio!')
        elif not studio:
            # get/create `Studio` from `new_studio` and use it for `studio` field
            studio, created = Studio.objects.get_or_create(name=new_studio)
            self.cleaned_data['studio'] = studio

        return super(FilmForm, self).clean()

Then, in your view, all you need is:

if form.is_valid():
    form.save()

这篇关于用django形式保存新的外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆