使用多个键值进行 django html 模板请求

Posted

技术标签:

【中文标题】使用多个键值进行 django html 模板请求【英文标题】:Making a django html template request with multiple key values 【发布时间】:2017-04-11 01:36:00 【问题描述】:

我是使用 Django 甚至创建网站的新手,所以如果我对我所面临的问题提供的细节太少/太多,请多多包涵。此外,我上周大部分时间都在浏览 SO 页面、博客、Django 教程、Django 文档等,试图自己解决问题。也许我忽略了某些事情,或者我只是不走运,但我发现的任何东西都无法完全解决我的特殊情况。大多数示例似乎都侧重于处理 views.py 中的请求,而不是如何在 Django 模板中发出原始请求。

我有一个 Django 模板 view_table.html,它向用户显示一个 Bootstrap DataTable 表对象。此表的第二列是名为 MyRow_ID 的 BigIntegerField。我目前在 MyCode.js 中有代码,允许用户突出显示多行,当单击按钮 modify_button 时,MyRow_ID 值选定的行(例如 [2, 13, 14])被捕获到名为 sent_data 的 JS 字典中。捕获这些值后,我希望 modify_button 创建一个 GET 请求,该请求会随之发送 sent_data。在 urls.py 中匹配并调用 views.py 中的 modify_data 函数后,modify_data 应该会呈现一个新页面modify_table.html 同时传回与 MyRow_ID 匹配的模型实例,以便仅显示所选行的数据。我想我已经很接近了,也许我只需要对正则表达式进行调整,但这是我的问题:

    如何在 Django 模板 view_table.html 中创建将 sent_data 传递给 Django 的 GET 请求?目前我正在使用一个表单,其中 methodaction 属性设置为 "GET""% url 'modify_data' sent_data=sent_data %"。我假设应该使用 GET 而不是 POST,因为请求没有修改后端,它更像是“过滤视图”类型的请求。这是一个正确的假设吗?请求的 url 是什么样的?假设 MyRow_ID 值为 [2,13,14]。获取请求是否类似于 /modify_data/matched_row_1=2&matched_row_2=13&matched_row_3=14?我是否必须自己在模板中通过迭代 sent_data 并附加“matched_row_n=”字符串来创建这个 url 字符串,还是有更简单的方法让模板在请求中自动创建它? 应该在 myapp/urls.py 中使用什么正确的正则表达式模式,因为 sent_data 可能有 1 到 n 个唯一的 MyRow_ID 值,假设分别选择了 1 到 n 行? (显然,健壮的代码将包括处理选择 0 行并单击 modify_button 的情况,但我们暂时将其放在一边。)目前我在 /myapp/view_data/ 处遇到 NoReverseMatch 错误:使用参数“()”和关键字参数“u'sent_data': ''' 反转'modify_data'。 我是使用正则表达式的新手,我知道我在 myapp/urls.py 是错误的。 myapp/views.py 中的代码是否可以正确过滤匹配的模型实例并使用所选行呈现 modify_table.html

view_table.html

<!DOCTYPE html>
<html>
  <head>
    ## Bunch of code… ##
  </head>
  <body>
    <div class="col col-xs-12 text-right">
      <form style="display" method="get" action="% url 'modify_data' sent_data=sent_data %">
        <button id="modify_button" type="button" class="btn btn-primary btn-create">Modify Data</button>
      </form>
    </div>
    <br><br><br>
    <table id="my_table">
      ## Code that displays my_table ##
    </table>
    <!-- Execute JS scripts -->
    <script type="text/javascript" src="% static "myapp/js/jquery-1.12.0.min.js" %"></script>
    <script type="text/javascript" src="% static "myapp/js/jquery.dataTables.min.js" %"></script>
    <script type="text/javascript" src="% static "myapp/js/bootstrap.min.js" %"></script>
    <script type="text/javascript" src="% static "myapp/js/dataTables.bootstrap.min.js" %"></script>
    <script type="text/javascript">
      var sent_data = [];
    </script>
    <script type="text/javascript" src="% static "myapp/js/MyCode.js" %"></script>
  </body>
</html>

MyCode.js

$(document).ready(function()
  var oTable = $('#my_table').DataTable();
  var selected_data = [];

  $('#my_table tbody').on('click','tr',function()
    $(this).toggleClass('active');
  );

  $('#modify_button').click(function(event)
    selected_data = $.map(oTable.rows('.active').data(), function (item) 
      return item[1]
    );
    sent_data =  'modify_rows': selected_data ;
  );
);

我应该注意我使用的是 MyRow_ID 而不是本机 DataTable 属性 rowID 因为我假设 DataTable 是自动创建的 rowID与 Django 使用的自动创建的主键 (pk) 不匹配。这是一个正确的假设吗?

myapp/urls.py

from django.conf.urls import url
from . import views
from .models import MyDataModel

urlpatterns = [
                url(r'^view_data/$', views.view_data, name='view_data'),
                url(r'^modify_data/(?P<sent_data>\d+)/$', views.modify_data, name='modify_data'),
              ]

myapp/views.py

from django.forms import modelformset_factory
from django.shortcuts import render
from django.http import HttpResponse
from .models import MyDataModel

def view_data(request):
  myData = MyDataModel.objects.all()
  return render(request, 'myapp/view_table.html', 'myData': myData)

def modify_data(request, sent_data):
  MyDataFormSet = modelformset_factory(MyDataModel, fields=('MyRow_ID','MyRow_Text'))
  if request.method == 'GET':
    selected_rows = sent_data['modify_rows']
    ## selected_rows = request.GET['modify_rows']
    formset = MyDataFormSet(queryset=MyDataModel.objects.filter(MyRow_ID__in=selected_rows))
    selected_data = MyDataModel.objects.filter(MyRow_ID__in=selected_rows)
    return render(request, 'myapp/modify_data.html', 'formset': formset, 'selected_data': selected_data)
  else:
    return HttpResponse('A GET request was not received.')

最后,modify_data.html

<!DOCTYPE html>
<html>
  <head>
    ## Bunch of code… ##
  </head>
  <body>
    <div class="col col-xs-12 text-right">
      <form method="post" action="">
        % csrf_token %
         formset 
        <button id="submit_changes" type="button" class="btn btn-primary btn-create">Submit Changes</button>
      </form>
    </div>
    <br><br><br>
    <table id="selected_rows_table">
      ## Code that displays selected rows passed as selected_data ##
    </table>
  </body>
</html>

非常感谢您的帮助,提前感谢您!

【问题讨论】:

【参考方案1】:

通过反复试验和良好的老式谷歌搜索,我能够解决上述问题,并更好地理解查询字符串、正则表达式模式,甚至如何使用 AJAX 请求来实现我的最初目标。

我最初的目标是允许用户选择多行数据,单击一个按钮,然后在一个表单中同时编辑它们,所述表单要么在新页面上呈现,要么在模式中呈现。以下帖子/博客对解决每个问题都非常有帮助:

关于 url、请求/响应和模型表单集的 Django 文档:

https://docs.djangoproject.com/en/1.10/topics/http/urls/

https://docs.djangoproject.com/en/1.10/ref/request-response/

https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#model-formsets

Bootstrap 模态创建指南:

https://coolestguidesontheplanet.com/bootstrap/modal.php

了解 url 和查询字符串如何处理单个键的多个值:

http://meyerweb.com/eric/tools/dencoder/(用于测试)

How to pass multiple values for a single URL parameter?

Capturing url parameters in request.GET

Django AJAX 表单使用示例:

http://schinckel.net/2013/06/13/django-ajax-forms/

处理来自服务器的 AJAX 请求响应并刷新页面的代码:

Update div with jQuery ajax response html

关于为单个键使用具有多个值的查询字符串时需要注意的重要一点,例如说我的 GET 请求的 url 类似于 www.myurl.com/?page=1&page=2&page=3;当使用 AJAX GET 请求时,它将使用 www.myurl.com/?page[]=1&page[]=2&page[]=3 为该 url 创建一个查询字符串,即添加“ []" 括号表示具有多个值的任何键。在处理请求时检索views.py 中“page”键的所有值的常用答案(如Django 和其他人所记录的)是使用request.GET.getlist('page')。这行不通。您需要使用 request.GET.getlist('page[]')。在 request.method.getlist() 中添加括号或从请求的 url 中的原始查询字符串中删除它们。

最后,这里有一些修改后的代码,解决了我最初的问题:

view_data.html 中,更新了表单:

<form id="modify_form" method="post" action="% url 'modify_data' %">
  % csrf_token %
   formset 
</form>

myapp/urls.py 中,修复了 url finder 以处理传递的任何查询字符串:

url(r'^modify_data/$', views.modify_data, name='modify_data'),

myapp/views.py 中,更改 modify_data 代码:

def modify_data(request):
  MyDataFormSet = modelformset_factory(MyDataModel, fields=('MyRow_ID','MyRow_Text'))
  if request.is_ajax():
    template = 'myapp/view_data.html'
  else:
    template = 'myapp/modify_data.html'

  if request.method == 'GET':
    selected_rows = request.GET.getlist['modify_rows[]']
    formset = MyDataFormSet(queryset=MyDataModel.objects.filter(MyRow_ID__in=selected_rows))
    selected_data = MyDataModel.objects.filter(MyRow_ID__in=selected_rows)
    return render(request, template, 'formset': formset, 'selected_data': selected_data)
  else:
    return HttpResponse('A GET request was not received.')

MyCode.js 中,代码已更新以反映使用模态表单、AJAX GET 请求并使用 Django view.py 的响应刷新 DOM:

$("#modify_button").click(function()
  selected_data = $.map(oTable.rows('.active').data(), function (item) 
   return item[1]
  );

  $.ajax(
    // The URL for the request
    url: URL,

    // The data to send (will be converted to a query string)
    data: 
      modify_rows: selected_data,
    ,

    // Whether this is a POST or GET request
    type: "GET",
  )
    // Code to run if the request succeeds (is done);
    // The response is passed to the function
    .done(function( json ) 
      var forms_result = $('<div />').append(json).find('#modify_form').html();
      $('#modify_form').html(forms_result);
      var table_result = $('<div />').append(json).find('#my_table').html();
      $('#my_table').html(table_result);
    )
    // Code to run if the request fails; the raw request
    // and status codes are passed to the function
    .fail(function( xhr, status, errorThrown ) 
      alert( "Sorry, there was a problem!" );
      console.log( "Error: " + errorThrown );
      console.log( "Status: " + status );
      console.dir( xhr );
    )
);

希望所有这些对其他人有所帮助,如果没有,这整个过程对我来说是一次很棒的学习经历!

【讨论】:

以上是关于使用多个键值进行 django html 模板请求的主要内容,如果未能解决你的问题,请参考以下文章

在多个 django 模板文件中显示相同 html 块的最佳 DRY 方法

Django之模板渲染

在 Django 循环模板中对第二个模型使用键值查找?

Django 模板标签 - 返回多个值或对象

循环模板的键值 - Django 查询

django:相同的模板标签,但在多个继承的 html 模板中