用django形式保存新的外键 [英] Save new foreign key with django form
问题描述
我有两个模型:
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():
pre>
form.save()
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 aModelForm
.Form
doesn't have asave
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屋!