Django在表单中自动设置外键(使用基于类的视图)
我想使用一个表单从一个人的页面生成一个新对象(比如一本书),这样新书就可以通过外键自动与此人关联,但是我在让此人与表单正确关联和保存时遇到了麻烦。对于我的模型,我有:Django在表单中自动设置外键(使用基于类的视图),django,django-forms,Django,Django Forms,我想使用一个表单从一个人的页面生成一个新对象(比如一本书),这样新书就可以通过外键自动与此人关联,但是我在让此人与表单正确关联和保存时遇到了麻烦。对于我的模型,我有: class Person(models.Model): p_id = models.PositiveIntegerField(primary_key=True, unique=True) class Book(models.Model): person = models.ForeignKey(Person)
class Person(models.Model):
p_id = models.PositiveIntegerField(primary_key=True, unique=True)
class Book(models.Model):
person = models.ForeignKey(Person)
title = models.CharField(max_length=100)
然后我有一个自定义表单来创建一本书:
class AddBookForm(forms.ModelForm):
class Meta:
model = Book
fields = ('title', 'person',)
widgets = {
'person': forms.HiddenInput,
}
以及创建该书的视图(该视图还提供了该人的pk
(p_id
):
我尝试了各种方法来实现这一点:
- 使用
预先填充Person字段,但由于某些原因,当输入设置为hidden(令人沮丧)时,这会消失get_initial
- 在视图中修改
方法,但这只发生在表单已经被验证之后,因此我需要在此之前添加Personform\u valid
- 修改表单类中的
方法,但这仅在表单通过clean\u person
方法验证后发生clean
clean
方法。然而,我不知道如何在这一点上的人,在表格已经被发送清洁。在视图中,我可以使用Patient.objects.get(p_id=self.kwargs.get('pk'))访问它
是否有某种方法可以将数据添加到我视图中的表单中(作为基于类的视图),使其不会被剥离或是否有某种方法可以在此时访问Person或p\u id
外键,以clean
方法添加数据?您的做法是错误的:Person不是用户输入,所以这些信息不应该存在于表单中。您可以按如下方式重写form\u valid
方法:
class AddBook(CreateView):
model = Book
def form_valid(self, form):
form.instance.person_id = self.kwargs.get('pk')
return super(AddBook, self).form_valid(form)
这将在表单用于保存数据的实例上设置person\u id
属性,然后调用super
方法保存该实例并返回重定向 由于ID随请求一起发送,因此表单不需要person字段。相反,您需要在保存书籍之前添加此人
您的表格应为:
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ('title',)
你的观点应该是这样的:
from django.shortcuts import get_object_or_404
from django.shortcuts import render, redirect
def create_book(request, person_id):
# If the person_id is not valid, don't go forward.
# return a 404 instead.
person = get_object_or_404(Person, pk=person_id)
book_form = BookForm(request.POST or None)
if book_form.is_valid():
new_book = book_form.save(commit=False) # Don't save it yet
new_book.person = person # Add person
new_book.save() # Now save it
return redirect('/')
return render(request, 'book_form.html', {'form': book_form})
在urls.py
中,确保将id传递给此视图:
url(r'book/add/(?P<person_id>\d+)/$', create_book, name='create_book')
现在,您的个人模型将具有一个自动的pk
属性,该属性将是主键(无论在数据库中实际调用什么)。如果用户未选择该书,您如何知道该书与哪个人关联?他们单击“创建书”在一个人的页面上,该页面的id将随请求一起发送。我几乎已经尝试过了。不过有两个窍门:我必须将该字段从表单中取出,以便它进行验证,我一直在尝试form.instance.p\u id
而不是person\u id
。我仍然不完全理解为什么它是person\u id.
我得到的person
部分,因为那是字段名。但是为什么\u id
?在这种情况下,这是否等同于pk
?是的:外键总是由两个属性组成;外部对象(模型实例)和外键(引用对象的主键)。外键属性总是在外键模型属性的名称后附加\u id
,这是实际保存到数据库中的字段。实际上,您必须将字段从表单中去掉。注意,在Python 3中,对的调用可以简化为super()
这是一个非常不基于分类的视图;)提出了同样的问题,如果他需要根据peraon实例做一些逻辑,会怎么样?按照您的方式,在form clean()方法中无法使用此人
url(r'book/add/(?P<person_id>\d+)/$', create_book, name='create_book')
class Person(models.Model):
name = models.CharField(max_length=200) # Or some other field