将django-tables2中表格排序请求由GET改为POST
解决django-tables2列排序用POST请求替代GET的方案
嘿,我懂你现在的困扰——django-tables2自带的列排序默认是发GET请求,但你想把排序操作整合到现有的POST表单里对吧?下面给你几个实用的解决方案:
方法一:用JavaScript拦截排序点击,转成POST提交
这个方法改动最小,只需要在模板里加一段JS,把表头的排序链接点击事件改成提交表单的动作:
{% load django_tables2 %} <form id="test" action="{% url 'myview' %}" method="post"> {% csrf_token %} <!-- 你的按钮、过滤器等表单元素 --> <div class="row" style=" white-space: nowrap; top: 950px;"> <div class="form-group col-lg-7 center"> {% render_table table %} </div> </div> </form> <script> // 监听所有表头的排序链接 document.querySelectorAll('table th a').forEach(sortLink => { sortLink.addEventListener('click', function(e) { e.preventDefault(); // 阻止默认的GET跳转 // 从链接里提取排序参数(比如从?sort=mycolumn里拿到mycolumn) const sortParam = new URL(this.href).searchParams.get('sort'); const form = document.getElementById('test'); // 先移除之前可能存在的sort隐藏输入 const oldSortInput = form.querySelector('input[name="sort"]'); if (oldSortInput) oldSortInput.remove(); // 创建新的隐藏输入来传递排序字段 const sortInput = document.createElement('input'); sortInput.type = 'hidden'; sortInput.name = 'sort'; sortInput.value = sortParam; // 把输入加到表单里,然后提交 form.appendChild(sortInput); form.submit(); }); }); </script>
然后在你的视图函数里,从request.POST.get('sort')获取排序参数就行,和原来处理GET的逻辑基本一致,只是换了获取方式。
方法二:自定义django-tables2表头模板,直接生成POST表单
如果不想用JS,也可以通过自定义表头模板,把排序链接换成内嵌的小表单,点击表头就提交POST请求:
- 先创建一个自定义表头模板,比如
tables/column_header.html:
{% load django_tables2 %} {% if column.orderable %} <th {{ column.attrs.th.as_html }}> <form method="post" action="{% url 'myview' %}" style="margin: 0; padding: 0;"> {% csrf_token %} <!-- 把当前表单的其他参数(比如过滤器值)也传过去 --> {% for key, value in request.POST.items %} {% if key != 'sort' %} <input type="hidden" name="{{ key }}" value="{{ value }}"> {% endif %} {% endfor %} <!-- 排序参数 --> <input type="hidden" name="sort" value="{{ column.order_by_alias }}"> <!-- 把表头文字做成按钮,样式和原来的链接一致 --> <button type="submit" style="background: none; border: none; cursor: pointer; color: inherit; text-decoration: underline;"> {{ column.header }} {% if column.is_ordered %} {% if column.order == 'asc' %}↑{% else %}↓{% endif %} {% endif %} </button> </form> </th> {% else %} <th {{ column.attrs.th.as_html }}>{{ column.header }}</th> {% endif %}
- 在你的Table类里指定这个自定义模板:
import django_tables2 as tables class MyTable(tables.Table): class Meta: model = YourModel template_name = "django_tables2/bootstrap.html" # 你当前用的表格模板 column_header_template = "tables/column_header.html" # 刚才创建的表头模板
这个方法完全用django-tables2的扩展能力,不需要额外JS,但要注意把现有表单的参数都通过隐藏输入传递,避免排序后过滤器失效。
方法三:后端兼容GET和POST两种排序参数
如果想同时兼容原来的GET排序和新的POST排序,可以在视图里同时从GET和POST里取参数:
def myview(request): # 优先从POST取,没有的话再从GET取 sort_by = request.POST.get('sort') or request.GET.get('sort') queryset = YourModel.objects.all() # 处理排序 if sort_by: queryset = queryset.order_by(sort_by) table = MyTable(queryset) # 其他表单逻辑... return render(request, 'mytemplate.html', {'table': table})
这种方式可以和前面的JS方法配合,既保留原有功能,又实现POST排序。
内容的提问来源于stack exchange,提问作者DalinDad
相关产品推荐
相关产品推荐

