代码之家  ›  专栏  ›  技术社区  ›  PVitt

创建两个模型之一时保存它们之间的关系

  •  0
  • PVitt  · 技术社区  · 6 年前

    我有三个(简化的)模型,我们称之为 Location , Thing Where :

    class Location(models.Model):
        name = models.CharField()
    class Thing(models.Model):
        name = models.CharField()
    class Where(models.Model):
        location = models.ForeignKey(to = Location)
        thing = models.ForeignKey(to = Thing)
    

    然后我用了通用的 CreateView 创建一个 位置 . 但我努力创造一种观点 事情 . 我想要的是这样的表格:

    class ThingForm(forms.Form):
        name = forms.CharField()
        location = forms.ModelChoiceField(queryset = Location.objects.all())
    

    此窗体获取用于创建新的 事情 但创建新的 在哪里? . 但是,我不知道如何创造新的 在哪里? .

    我的视图如下:

    class ThingCreateView(generic.CreateView):
        model = Thing
        form_class = ThingForm
        success_url = 'somewhere/'
    

    我读到我必须重写视图的 form_valid 验证表单数据后执行某些操作的函数:

    def form_valid(self, form):
        where = Where(location = form.location, thing = ???)
        where.save()
        return super().form_valid(form)
    

    问题是:把什么作为东西?据我所知,新创建的 事情 尚未保存,因此无法在数据库的 在哪里? 表。

    我怎样才能在 事情 位置 创建一个 事情 ?或者这是错误的方法,我需要编写自己的视图而不是使用通用的CreateView?或者是别的什么?

    1 回复  |  直到 6 年前
        1
  •  0
  •   PVitt    6 年前

    对于记录:所描述的构造是不可能的。这个 documentation 说:

    如果一个模型有一个自动递增的主键,那么这个自动递增的值将在你第一次调用save()时计算并保存为你的对象上的一个属性,因为这个值是由你的数据库而不是由dja来计算的。非政府组织。

    由于where表将包含location和thing的主键,因此在向该表添加新行时,它们需要可用。因此,解决方案是不使用通用的CreateView,而是编写自定义视图:

    def create(request):
        if request.method == 'POST':
            form = CreateForm(request.POST)
            if form.is_valid():
                t = Thing(name = form.cleaned_data['name'])
                t.save()
                w = Where(
                    thing = t,
                    location = form.cleaned_data['location'])
                w.save()
                return HttpResponseRedirect('/thing/{0}'.format(thing.id))
        else:
            form = CreateForm()
    
        return render(request, 'create_form.html', {'form': form})