Django:从表中提取数据以初始填充表单

时间:2017-03-31 12:48:21

标签: python django forms django-forms django-views

我希望最初使用另一个应用程序的数据填充我的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的部分?

谢谢

2 个答案:

答案 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