使用多个键值进行 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 请求?目前我正在使用一个表单,其中 method 和 action 属性设置为 "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 模板请求的主要内容,如果未能解决你的问题,请参考以下文章