我有3个(简化的)模型,我们将它们称为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
创建了一个Location
。但是我很难创建一个视图来创建Thing
。我想要的是这样的表格:
class ThingForm(forms.Form):
name = forms.CharField()
location = forms.ModelChoiceField(queryset = Location.objects.all())
此表单使用用于创建新的Thing
的数据,但也使用创建新的Where
的日期。但是,我不知道如何创建新的Where
。
我的视图如下:
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)
问题是:什么东西放?据我了解的文档,新创建的Thing
尚未保存,因此我无法在数据库的Where
表中引用它。
在创建Thing
时如何在Location
和Thing
之间建立关系?还是这是错误的方法,我需要编写自己的视图而不是使用通用的CreateView?甚至不同的东西?
答案 0 :(得分:0)
作记录:所描述的构造是不可能的。 documentation说:
如果模型具有AutoField(自动递增的主键),则将在您首次调用save()时计算该自动递增的值并将其另存为对象上的属性[..]在调用save()之前先告诉ID值是什么,因为该值是由数据库而不是Django计算的。
由于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})