如何对Django queryset进行JSON解析以便在JavaScript中处理数据?
解决方案
首先先修正视图代码笔误:你当前views.py中存在变量名不匹配问题,定义的查询集变量为all_contents,但Paginator传参、上下文赋值时使用了未定义的contents,修改后基础视图代码如下:
from django.forms.models import model_to_dict from django.core.paginator import Paginator def main_page(request): all_contents = Contents.objects.all() paginator_contents = Paginator(all_contents, 10) page = request.GET.get('page') all_contents_paginated = paginator_contents.get_page(page) # 可选:提前把分页对象转成序列化后的列表,也可以用自定义过滤器在模板处理 paginated_data = [model_to_dict(item) for item in all_contents_paginated] context = { 'all_contents_paginated' : all_contents_paginated, 'paginated_data': paginated_data } return render(request, 'main/home.html', context)
以下是3种可落地的实现方案:
方案1:少量字段直接拼接参数(最简单,适合字段≤5个的场景)
直接在onclick事件中把需要的字段手动拼成JS对象,所有字符串字段加escapejs过滤器处理特殊字符:
{% for c in all_contents_paginated %} <div class="text-m"> {{c.author}} </div> <div class="text-s" onclick="DetailModal({id: {{c.id}}, author: '{{c.author|escapejs}}', body: '{{c.body|escapejs}}'})"> {{c.body}} </div> {% endfor %} <script> function DetailModal(contentObj) { // 直接拿到JS对象,不用解析,直接使用即可 console.log(contentObj.author, contentObj.body) // 后续模态框渲染逻辑 } </script>
方案2:全局预存序列化数据(推荐,适合字段多、需要频繁操作数据的场景)
把整个分页的序列化数据提前注入到全局JS变量中,点击时仅传ID索引对应数据,DOM结构更干净:
<script> // 把Django传来的序列化数据转成JS对象,这里要加safe过滤器避免Django自动转义引号 const allContentData = JSON.parse('{{ paginated_data|json_script:"content-data"|safe }}') function DetailModal(contentId) { const contentObj = allContentData.find(item => item.id === contentId) // 直接使用contentObj即可 } </script> {% for c in all_contents_paginated %} <div class="text-m"> {{c.author}} </div> <div class="text-s" onclick="DetailModal({{c.id}})"> {{c.body}} </div> {% endfor %}
方案3:自定义模板过滤器序列化单个对象
如果需要在多个页面复用单个模型对象转JS对象的能力,可以自定义Django模板过滤器:
- 先在APP下新建
templatetags目录,新增custom_filters.py:
import json from django import template from django.forms.models import model_to_dict register = template.Library() @register.filter def to_json(obj): return json.dumps(model_to_dict(obj))
- 模板中使用:
{% load custom_filters %} {% for c in all_contents_paginated %} <div class="text-m"> {{c.author}} </div> <div class="text-s" onclick="DetailModal({{ c|to_json|safe }})"> {{c.body}} </div> {% endfor %} <script> function DetailModal(contentObj) { // 直接拿到JS对象使用 } </script>
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

