【问题标题】:Django : Extract data from table to initially populate a formDjango:从表中提取数据以最初填充表单
【发布时间】:2017-08-25 18:00:23
【问题描述】:

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

谢谢

【问题讨论】:

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


    【解决方案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})
    

    【讨论】:

      【解决方案2】:

      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

      【讨论】:

      • 嘿,@Deadpool 我正在通过我的答案。您是否认为此答案有帮助?愿意接受吗?
      猜你喜欢
      • 2011-10-21
      • 2012-08-14
      • 2018-09-02
      • 2017-05-15
      • 1970-01-01
      • 2023-02-02
      • 2018-08-15
      • 2018-04-24
      • 1970-01-01
      相关资源
      最近更新 更多