我希望最初使用另一个应用程序的数据填充我的Django表单。我按照这个SO示例来编写我的函数:
Initial populating on Django Forms
但是,我没有成功得到我想要的东西。这就是我的功能应该做的事情:
我有一个名为Person
的模型,其中包含许多信息(名字,...)和非常有用的unique number
,以区分每个人。
然后,我有另一个名为BirthCertificate
的模型,其中包含一个表格以创建出生法。在我的表单视图中,用户给出了这个unique number
,Django能够搜索好人(不是很难),最初填充我的表单(在Person.model和BirthCertificate.model之间有一些共同的字段)。
我有两个步骤:
我提交此信息,第一步应该首先填充公共字段。第二步效果很好。
这是我的功能,但有些事情仍无效:
def BirthCertificate_Form_unique_number(request) :
#User fill some fields
query_social_number = request.GET.get('social_number')
query_social_number_father = request.GET.get('social_number_father')
query_social_number_mother = request.GET.get('social_number_mother')
if query_social_number :
query_social_number_list = Person.objects.filter(social_number=query_social_number)
if query_social_number_list:
sc_obj = query_social_number_list[0]
#For example : sc_obj.lastname will extract lastname
# etc ...
else :
query_social_number_list = Person.objects.none()
initial_data = {
'lastname': sc_obj.lastname,
'firstname': sc_obj.firstname,
'birthday': sc_obj.birthday,
'sex' : sc_obj.sex,
'birthcity': sc_obj.birthcity
}
form = BirthCertificateForm(request.POST or None, initial=initial_data)
if form.is_valid() : # Check data
post = form.save()
return HttpResponseRedirect(reverse('BC_treated', kwargs={'id': post.id}))
else:
form = BirthCertificateForm()
parent1 = Person.objects.filter(social_number=query_social_number_father)
parent2 = Person.objects.filter(social_number=query_social_number_mother)
form = BirthCertificateForm(request.POST or None)
form.fields['fk_parent1'].queryset = parent1
form.fields['fk_parent2'].queryset = parent2
context = {
"form" : form,
"person" : person,
}
return render(request, 'BC_form2.html', context)
如何重新组织query_social_number
的部分?
谢谢
答案 0 :(得分:1)
无法正常工作的原因是:sc_obj
不会出现,以便在未发送social_number
时填充初始数据。理想情况下,它会引发异常“sc_obj
未定义”。
您可以通过将其放在try: except:
块中然后打印/记录堆栈跟踪来避免这种情况。
如果表单无效,您也会重新填充表单。通过这样做,您将丢失表单中的错误部分。
让我知道这是否有效/这是你所期待的:
def BirthCertificate_Form_unique_number(request):
# User fill some fields
if request.method == 'GET':
data = request.GET
persons = Person.objects.filter(social_number=data.get('social_number', ''))
if persons:
sc_obj = persons.first() # .latest()
# For example : sc_obj.lastname will extract lastname
# etc ...
initial_data = {
'lastname': sc_obj.lastname,
'firstname': sc_obj.firstname,
'birthday': sc_obj.birthday,
'sex': sc_obj.sex,
'birthcity': sc_obj.birthcity
}
form = BirthCertificateForm(initial=initial_data)
else:
query_social_number_father = request.GET.get('social_number_father')
query_social_number_mother = request.GET.get('social_number_mother')
form = BirthCertificateForm()
parent1 = Person.objects.filter(social_number=query_social_number_father)
parent2 = Person.objects.filter(social_number=query_social_number_mother)
form.fields['fk_parent1'].queryset = parent1
form.fields['fk_parent2'].queryset = parent2
elif request.method == 'POST':
form = BirthCertificateForm(request.POST)
if form.is_valid(): # Check data
post = form.save()
return HttpResponseRedirect(reverse('BC_treated', kwargs={'id': post.id}))
else:
raise Exception("Method not allowed")
return render(request, 'BC_form2.html', {"form": form, "person": person})
答案 1 :(得分:1)
<强> TL; DR:强>
from django.views.decorators.http import require_http_methods
@require_http_methods(["GET", "POST"]) # Allow only GET, POST methods
def BirthCertificate_Form_Unique_Number_View(request): #Add View in name for clarity
# GET request case
if request.method == "GET":
data = request.GET
sc_obj = Person.objects.get(social_number=data.get('social_number', ''))
if sc_obj:
initial_data = {
'lastname': sc_obj.lastname,
'firstname': sc_obj.firstname,
'birthday': sc_obj.birthday,
'sex': sc_obj.sex,
'birthcity': sc_obj.birthcity
}
form = BirthCertificateForm(initial=initial_data)
else:
query_social_number_father = data.get('social_number_father')
query_social_number_mother = data.get('social_number_mother')
form = BirthCertificateForm()
parent1 = Person.objects.get(social_number=query_social_number_father)
parent2 = Person.objects.get(social_number=query_social_number_mother)
form.fields['fk_parent1'] = parent1
form.fields['fk_parent2'] = parent2
# POST request case
elif request.method == "POST":
form = BirthCertificateForm(request.POST)
# Assuming this works as intended
if form.is_valid(): # Check data
post = form.save()
return HttpResponseRedirect(reverse('BC_treated', kwargs={'id': post.id}))
context = {
"form" : form,
"person" : person,
}
return render(request, 'BC_form2.html', context)
您提供的方法是尝试填写表单而不等待请求中的social_number
数据。因此,它默认为代码的else
部分。
您正试图从Person模型中获取一个对象,因为ID是唯一的。这意味着,一个人存在并且是唯一的或根本不存在。上面提到的,您不需要过滤您的查询集,而只需要检索一个条目(如果存在)并使用Person.objects.get(...)
完成。
使用@require_http_methods(["GET", "POST"])
装饰器只允许对视图发出GET和POST请求,并且必须在代码中检查这两个请求。基本上,您将案件限制为仅两个,其余服务将响应:Method not allowed
。