将对象从 Django 传递到 Javascript DOM

发布于 2024-12-01 04:33:00 字数 817 浏览 8 评论 0 原文

我正在尝试使用 javascript 将查询集从 Django 传递到模板。

我尝试了不同的方法来解决这个问题:

1。 ,Javascript 在尝试解析对象时变得一团糟

正常方法 - 由于命名法 [ &gt Object:ID &lt, &gt Object:ID &lt,... ] Django 视图

django_list = list(Some_Object.objects.all())

模板 HTML + JS

<script type="text/javascript" >
    var js_list = {{django_list}};
</script>

2. JSON 方法 - Django 无法将对象列表转换为 json 字符串 不是 JSON 可序列化

Django 视图

django_list = list(Some_Object.objects.all())
json_list = simplejson.dumps(django_list)

模板 HTML + JS

<script type="text/javascript" >
    var js_list = {{json_list}};
</script>

所以,我在这里需要一些帮助:)

有人有什么建议/解决方案吗?

谢谢!

I'm trying to pass a Query Set from Django to a template with javascript.

I've tried different approaches to solve this:

1. Normal Approach - Javascript gets all messed up with trying to parse the object because of the nomenclature [ > Object:ID <, > Object:ID <,... ]

Django View

django_list = list(Some_Object.objects.all())

Template HTML + JS

<script type="text/javascript" >
    var js_list = {{django_list}};
</script>

2. JSON Approach - Django fails on converting the object list to a json string
is not JSON serializable

Django View

django_list = list(Some_Object.objects.all())
json_list = simplejson.dumps(django_list)

Template HTML + JS

<script type="text/javascript" >
    var js_list = {{json_list}};
</script>

So, I need some help here :)

Any one has any suggestion / solution?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

倒数 2024-12-08 04:33:00

同样的问题,“更好”(更新)答案:Django Queryset to dict for use in json

vashishtha-jogi:

更好的方法是使用 DjangoJSONEncoder。它支持十进制。

导入json
从 django.core.serializers.json 导入 DjangoJSONEncoder

价格 = Price.objects.filter(product=product).values_list('price','valid_from')

prices_json = json.dumps(列表(价格), cls=DjangoJSONEncoder)

非常容易使用。无需跳过任何障碍来转换个人
要浮动的字段。

更新:将答案更改为使用内置 json 而不是 simplejson。

这个答案在我的谷歌搜索中经常出现,并且有很多观点,更新它并避免其他人挖掘这样的内容似乎是个好主意。假设使用 Django 1.5。

Same Question, "Better"(more recent) answer: Django Queryset to dict for use in json

Answer by vashishtha-jogi:

A better approach is to use DjangoJSONEncoder. It has support for Decimal.

import json
from django.core.serializers.json import DjangoJSONEncoder

prices = Price.objects.filter(product=product).values_list('price','valid_from')

prices_json = json.dumps(list(prices), cls=DjangoJSONEncoder)

Very easy to use. No jumping through hoops for converting individual
fields to float.

Update : Changed the answer to use builtin json instead of simplejson.

This is answer came up so often in my google searches and has so many views, that it seems like a good idea to update it and save anyone else from digging through SO. Assumes Django 1.5.

忆梦 2024-12-08 04:33:00

好的,我找到了解决方案!

主要是因为没有引用结果。当 Javascript 尝试解析该对象时,该对象未被识别为字符串。

所以,第一步是:

var js_list = {{django_list}}; 

更改为:

var js_list = "{{django_list}}";

之后我意识到 Django 正在转义字符,所以我必须像这样替换它们:

 var myJSONList = (("{{json_list}}").replace(/&(l|g|quo)t;/g, function(a,b){
                return {
                    l   : '<',
                    g   : '>',
                    quo : '"'
                }[b];
            }));

 myData = JSON.parse( myJSONList );

注意:我尝试使用此方法避免从 Django 转义字符

var js_list = "{{json_list|safe}}"; 

但这并不不起作用,因为它与引号混淆了。

最后,我找到了一种方法来避免在将其发送到 Javascript 之前转换为 JSON 的后端逻辑:

var myDjangoList = (("{{django_list |safe}}").replace(/&(l|g|quo)t;/g, function(a,b){
            return {
                l   : '<',
                g   : '>',
                quo : '"'
            }[b];
        }));

myDjangoList = myDjangoList.replace(/u'/g, '\'')
myDjangoList = myDjangoList.replace(/'/g, '\"')

myData = JSON.parse( myDjangoList );

我确信这可以改进,我把这个告诉你;)

感谢您的回答

希望它对其他人有帮助!

Ok, I found the solution!

Mostly it was because of not quoting the results. When Javascript was trying to parse the object this wasn't recognized as string.

So, first step is:

var js_list = {{django_list}}; 

changed to:

var js_list = "{{django_list}}";

After this I realized that Django was escaping characters so I had to replace them like this:

 var myJSONList = (("{{json_list}}").replace(/&(l|g|quo)t;/g, function(a,b){
                return {
                    l   : '<',
                    g   : '>',
                    quo : '"'
                }[b];
            }));

 myData = JSON.parse( myJSONList );

Note: I tried to avoid escaping characters from Django using this:

var js_list = "{{json_list|safe}}"; 

But this doesn't work because it gets confused with the quotes.

Finally I found a way to avoid the logic on the backend of converting to JSON before sending it to Javascript:

var myDjangoList = (("{{django_list |safe}}").replace(/&(l|g|quo)t;/g, function(a,b){
            return {
                l   : '<',
                g   : '>',
                quo : '"'
            }[b];
        }));

myDjangoList = myDjangoList.replace(/u'/g, '\'')
myDjangoList = myDjangoList.replace(/'/g, '\"')

myData = JSON.parse( myDjangoList );

I'm sure this can be improved, I let this to you ;)

Thanks for your answers

Hope it helps to someone else!

吃兔兔 2024-12-08 04:33:00

Django 查询集通过 JSON 序列化。某些字段类型(显然是日期)无法序列化。日期对象的解决方法发布在 关于 JSON 和 Python 的另一个问题

我建议直接在 JavaScript 本身中创建字典。给定这样的模型:

class Article(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField()
    content = models.TextField()

class Author(models.Model):
    article = models.ForeignKey("Article", related_name="authors")
    first_name=models.CharField(max_length=100)
    last_name=models.CharField(max_length=100)

我会在模板中执行类似的操作:

<script type="text/javascript">
    var articles = [
    {% for article in article_list %}
        {% if not forloop.first %},{% endif %}
        {
            title: "{{ article.title }}",
            slug: "{{ article.slug }}",
            content: "{{ article.content }}",
            authors: [
            {% for author in article.authors.all %}
                {% if not forloop.first %},{% endif %}
                {
                    first_name: "{{ author.first_name }}",
                    last_name: "{{ author.last_name }}",
                }
            {% endfor %}
            ]
        }
    {% endfor %}
    ]
</script>

如果您的问题措辞可能有点糟糕并且计划在

Django querysets are serializable by JSON. Some field types (such as date, apparently), can't be serialized at is. A workaround for date objects is posted in another question on JSON and Python.

I would recommend creating dictionaries directly in the JavaScript itself. Given models like this:

class Article(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField()
    content = models.TextField()

class Author(models.Model):
    article = models.ForeignKey("Article", related_name="authors")
    first_name=models.CharField(max_length=100)
    last_name=models.CharField(max_length=100)

I'd do something like this in the template:

<script type="text/javascript">
    var articles = [
    {% for article in article_list %}
        {% if not forloop.first %},{% endif %}
        {
            title: "{{ article.title }}",
            slug: "{{ article.slug }}",
            content: "{{ article.content }}",
            authors: [
            {% for author in article.authors.all %}
                {% if not forloop.first %},{% endif %}
                {
                    first_name: "{{ author.first_name }}",
                    last_name: "{{ author.last_name }}",
                }
            {% endfor %}
            ]
        }
    {% endfor %}
    ]
</script>

If you maybe worded the question a little poorly and aren't planning on inserting code in a <script> tag and actually need JSON for some reason, I'd simply do a loop in the view and create a list of dicts, which JSON has no problem serializing, and JavaScript no problem in understanding.

魄砕の薆 2024-12-08 04:33:00

编辑:请不要使用此方法,请参阅@agconti 的答案。

使用 escapejs 过滤器: https://docs.djangoproject.com/ en/1.4/ref/templates/builtins/#escapejs

转储列表的示例:

var foo = [{% for x in y %}'{{ x|escapejs }}',{% endfor %}]

EDIT: please don't use this method, see @agconti's answer.

Use the escapejs filter: https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#escapejs

Example of dumping a list:

var foo = [{% for x in y %}'{{ x|escapejs }}',{% endfor %}]
沩ん囻菔务 2024-12-08 04:33:00

从 Django 2.1 开始,就有 json-script 模板标签。来自文档:

json_script

安全地将 Python 对象输出为 JSON,并封装在标签中,
准备好与 JavaScript 一起使用。

参数:标签的 HTML“id”。

例如:

{{ value|json_script:"hello-data" }} 

如果 value 是字典 {'hello': 'world'},则输出将为:

&'},则输出为:

Since Django 2.1 there is the json-script template tag. From the docs:

json_script

Safely outputs a Python object as JSON, wrapped in a tag,
ready for use with JavaScript.

Argument: HTML “id” of the tag.

For example:

{{ value|json_script:"hello-data" }} 

If value is the dictionary {'hello': 'world'}, the output will be:

<script id="hello-data" type="application/json">
{"hello": "world"}
</script>

The resulting data can be accessed in JavaScript
like this:

var value = JSON.parse(document.getElementById('hello-data').textContent); 

XSS attacks are mitigated by escaping the characters “<”, “>” and “&”. For
example if value is {'hello': 'world</script>&'}, the output is:

<script id="hello-data" type="application/json">
    {"hello": "world\\u003C/script\\u003E\\u0026amp;"}
</script> 

This is compatible
with a strict Content Security Policy that prohibits in-page script
execution. It also maintains a clean separation between passive data
and executable code.

缱绻入梦 2024-12-08 04:33:00

您可以使用 安全escapejs Django 中的内置过滤器。

var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);

You can use the combination of safe and escapejs built-in filter in Django.

var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);
我很OK 2024-12-08 04:33:00

您的问题是,正如经常发生的那样,您的要求没有明确说明。您到底希望 JSON 是什么样子?你说你想“序列化查询集”,但以什么格式呢?您想要每个模型实例的所有字段、一个选择还是只是 unicode 表示形式?当你回答了这个问题后,你就会知道如何解决你的问题。

例如,一种方法可能是使用 values queryset 方法输出每个实例的字段字典,并将其序列化(您需要首先将其转换为列表):

data = SomeObject.objects.values('field1', 'field2', 'field3')
serialized_data = simplejson.dumps(list(data))

Your problem is that, as so often, your requirements are under-specified. What exactly do you want the JSON to look like? You say you want to "serialize the queryset", but in what format? Do you want all the fields from each model instance, a selection, or just the unicode representation? When you've answered that question, you'll know how to solve your problem.

One approach, for example, might be to use the values queryset method to output a dictionary of fields for each instance, and serialize that (you need to convert it to a list first):

data = SomeObject.objects.values('field1', 'field2', 'field3')
serialized_data = simplejson.dumps(list(data))
耶耶耶 2024-12-08 04:33:00

您必须将字符串标记为安全,以确保它不会被转义。

在我的一个项目中,我像这样使用它:

# app/templatetag/jsonify.py
from django import template
from django.utils.safestring import mark_safe
import json

register = template.Library()

@register.filter
def jsonify(list):
    return mark_safe(json.dumps(list))

在模板中

{% load jsonify %}
<script type="text/javascript" >
    var js_list = {{ python_list|jsonify|escapejs }};
</script>

,但您可能更喜欢仅添加 mark_safe 或在模板中使用 |safe 以避免所有 > 内容

如果问题是处理复杂的 python 对象,你可能必须像这样处理你的处理程序: Python 和 JavaScript 之间的 JSON 日期时间

You have to mark the string as safe to be sure it's not escaped.

in one of my project I use it like this:

# app/templatetag/jsonify.py
from django import template
from django.utils.safestring import mark_safe
import json

register = template.Library()

@register.filter
def jsonify(list):
    return mark_safe(json.dumps(list))

and in the template

{% load jsonify %}
<script type="text/javascript" >
    var js_list = {{ python_list|jsonify|escapejs }};
</script>

but you may prefer to just add mark_safe or use |safe in the template to avoid all > stuff

If the problem is for handling complex python object you may have to do your handler like this: JSON datetime between Python and JavaScript

是伱的 2024-12-08 04:33:00

Django 为您在此处尝试执行的场景提供内置帮助。它是这样的:

你的视图中有一个 python 序列、列表、字典等,我们称之为 py_object 。一种方法是在将其传递给渲染引擎之前对其进行 jsonify。

from django.shortcuts import render_to_response
import json  

然后稍后像这样使用...

render_to_response('mypage.html',{'js_object':json.dumps(py_object)})

在您的模板中,然后使用 safe 过滤器将已经 json 化的对象从 python 导入到 javascript 中,就像这样...

data = {{ js_object|safe }}

我希望这应该可以解决您的问题。

Django offers in-built help for the very scenario you are trying to do here. It goes something like this:

You have a python sequence, list, dictionary, etc in your view, let's call it py_object. One approach is to jsonify it before passing it to the rendering engine.

from django.shortcuts import render_to_response
import json  

Then later on use like this...

render_to_response('mypage.html',{'js_object':json.dumps(py_object)})

In you template, then use the safe filter to import the already jsonized object from python into javascript, like this...

data = {{ js_object|safe }}

That should solve your problem i hope.

美人如玉 2024-12-08 04:33:00

任何一个;

使用 {{ django_list }} 读取对象,然后删除不需要的字符

或执行;

{{ django_list | safe}}

either;

read object using {{ django_list }} and then remove unwanted characters

or do;

{{ django_list | safe}}
转角预定愛 2024-12-08 04:33:00

综合答案(我的环境:Django 2.0)

在views.py中

import json
data= []
// fil the list
context['mydata'] = json.dumps({'data':data})

在模板中

  <script type="text/javascript">
      var mydataString = "{{mydata|escapejs}}";
      console.log(JSON.parse(mydataString));
  </script>

Consolidated answer (my env: Django 2.0)

In views.py

import json
data= []
// fil the list
context['mydata'] = json.dumps({'data':data})

In template

  <script type="text/javascript">
      var mydataString = "{{mydata|escapejs}}";
      console.log(JSON.parse(mydataString));
  </script>
你又不是我 2024-12-08 04:33:00

让我发送整个查询集(同时保留字段名称;发送 object 而不是 list)。我使用了以下内容

    # views.py        
    units = Unit.objects.all()
    units_serialized = serializers.serialize('json', units)
    context['units'] = units_serialized

,仅在模板中使用 safe 标签

    # template.html
    <script>
            console.log({{units|safe}});
    </script>

For me to send the whole QuerySet (while preserving the fields names; sending object not list). I used the following

    # views.py        
    units = Unit.objects.all()
    units_serialized = serializers.serialize('json', units)
    context['units'] = units_serialized

and just use safe tag in the template

    # template.html
    <script>
            console.log({{units|safe}});
    </script>
樱桃奶球 2024-12-08 04:33:00

django 2.1 的注释

我发现这在 django 文档中有点令人困惑,所以简单地解释了一点简单的方法。

使用它

{{ my_info }}

我们通常会根据我们的需要 或循环它。但是,如果我们使用以下过滤器,

json_script 

我们可以安全地将此值输出为 JSON

{{ my_info|json_script:"my-info" }}

我们的数据已添加为 JSON,包装在脚本标记中,我们可以看到数据。我们现在可以通过在 JavaScript 中查找来使用该值,如下所示:

info = JSON.parse(document.getElementById('my-info').textContent);

NOTE for django 2.1

i found this a little confusing on django documentation so simply explaining a little bit easy way.

we would normally use this like

{{ my_info }}

or loop over it depending on what we needed. But if we use the following filter,

json_script 

we can safely output this value as JSON

{{ my_info|json_script:"my-info" }}

Our data has been added as JSON, wrapped in a script tag, and we can see the data. We can now use this value by looking it up in JavaScript like so:

info = JSON.parse(document.getElementById('my-info').textContent);
我还不会笑 2024-12-08 04:33:00

还要小心确保从 Django 正确输出 JSON 数据,否则前端的所有试验都将浪费时间。就我而言,我无法使用 JsonResponse 作为渲染函数的一部分,因此我执行了以下操作:

    def view(self, request):

        data = []
        machine_data = list(Machine.objects.filter(location__isnull=False).values_list('serial', 'location', 'customer__name'))
        data.append({
            "locations": machine_data,
        })

        return render(request, 'admin/company/device/map.html', {
            "machines": data
        })

在前端:

{% block content %}

    {{ machines_with_location|json_script:"machineLocationData" }}

    <div id="content-main">

        <h1>Title</h1>

        <script type="text/javascript">

            const locationDataFromJson = JSON.parse(document.getElementById('machineLocationData').textContent);

        </script>

    </div>

{% endblock %}

Be careful on also making sure that you output JSON data correctly from Django, otherwise all trials on the frontend side will be a waste of time. In my case I could not use JsonResponse as part of the render function so I did the following:

    def view(self, request):

        data = []
        machine_data = list(Machine.objects.filter(location__isnull=False).values_list('serial', 'location', 'customer__name'))
        data.append({
            "locations": machine_data,
        })

        return render(request, 'admin/company/device/map.html', {
            "machines": data
        })

And on the frontend:

{% block content %}

    {{ machines_with_location|json_script:"machineLocationData" }}

    <div id="content-main">

        <h1>Title</h1>

        <script type="text/javascript">

            const locationDataFromJson = JSON.parse(document.getElementById('machineLocationData').textContent);

        </script>

    </div>

{% endblock %}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文