首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用django表单保存新的外键

用django表单保存新的外键
EN

Stack Overflow用户
提问于 2012-01-25 08:39:37
回答 2查看 10.6K关注 0票数 8

我有两个模型:

代码语言:javascript
运行
复制
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)

我有一个电影表单,允许用户选择一个预先存在的Studio,或者键入一个新的Studio:

代码语言:javascript
运行
复制
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")

需要进行验证以确保new_studio名称不存在。如果用户输入new_studio,我希望保存工作室,然后保存新的电影。

代码语言:javascript
运行
复制
form = FilmForm(request.POST) 
if form.is_valid(): # All validation rules pass
    std = Studio(name = form.cleaned_data['new_studio'])
    std.save()

但是,如何使用全新的工作室id保存电影实例呢?我已经看过this question了,但是如果我在电影模型和电影表单中有更多的字段呢?如果我使用链接答案,我必须输入每个字段:

代码语言:javascript
运行
复制
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.)

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-25 09:26:17

实际上,您唯一的问题是使用了标准的Form而不是ModelFormForm没有save方法,因为它本身并不绑定到任何东西(即它不知道保存什么或保存到哪里)。

但是,如果使用ModelForm,则需要处理在表单中创建新工作室所涉及的所有逻辑。不过,这实际上更好,因为这样您就可以只使用表单,而不用担心其他任何事情:表单包含正确保存自身所需的所有逻辑。

代码语言:javascript
运行
复制
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()

那么,在您看来,您所需要的就是:

代码语言:javascript
运行
复制
if form.is_valid():
    form.save()
票数 6
EN

Stack Overflow用户

发布于 2015-03-23 07:48:40

我偶然发现了这个问题,我想我为未来的求职者找到了一个更好的答案。

Django附带了一个名为Inline Formsets的东西,它可以帮助你以一种形式管理关系。

你只需要创建你的模型,就像你用他们各自的ForeignKeys做的那样。然后在Forms.py中导入以下内容

代码语言:javascript
运行
复制
from django.forms.models import inlineformset_factory

然后:

代码语言:javascript
运行
复制
YOUR_FORMSET = inlineformset_factory(Model1,Model2)

回到您的views.py,您应该导入您的表单和新创建的YOUR_FORMSET。

这样做之后,您的方法应该像这样使用inlineformset:

代码语言:javascript
运行
复制
def add_question(request):

    if request.method == 'POST':


      form =AddQuestionForm(request.POST, request.FILES)
      if form.is_valid():
          new_question = form.save(commit=False)

          question_formset = QuestionFormset(request.POST, instance=new_question)
          if question_formset.is_valid():
              form.save()
              question_formset.save()
              return HttpResponseRedirect(reverse('polls:detail',args=(new_question.pk,)))
      else:
          print(form.errors)
    else:
        form = AddQuestionForm()
        question_formset = QuestionFormset(instance=Question())
    return render(request, 'polls/add.html', {'form':form, 'question_formset':question_formset,})

我使用的是我自己的例子,但是这个想法已经被解释过了。

如果你想阅读更具体的解释,请阅读我找到的这个很棒的blog post

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8996451

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档