【问题标题】:Is it possible to pass Ajax response as template context variable in Django?是否可以在 Django 中将 Ajax 响应作为模板上下文变量传递?
【发布时间】:2020-06-20 18:36:16
【问题描述】:

我向服务器发送了一个 Ajax 请求以获取一些过滤后的数据,这是我从服务器收到的示例:

(3) [{…}, {…}, {…}]
0: {id: 1, title: "12 Rue Longueil", slug: "12-rue-longueil", latitude: null, longitude: null, …}
1: {id: 2, title: "15 Rue Sherbrooke LM", slug: "15-rue-sherbrooke-lm", latitude: null, longitude: null, …}
2: {id: 3, title: "Cycle Neron", slug: "cycle-neron", latitude: "-73.5987000000000000", longitude: "45.4799000000000000", …}
length: 3
__proto__: Array(0)

以上数据是从控制台记录的。

我想在下面卡片中的 HTMl 标签中显示这些数据。

但为此我需要使用接收到的数据并使用 JavaScript 创建子级,例如document.createElement('DIV')。然后放置这些数据。

  $(document).on('submit', "#filterform", function (e) {

        e.preventDefault();

        $.ajax({
            type: 'GET',
            url: "{% url 'listing:search' %}",
            data: {
                listing_for: $('#listing_for').val(),
                // cutted
            },

            success: function (response) {
                const listings = eval(response);
    
                const content = document.getElementById('content');

                for (let i = 0; i < listings.length; i++) {
                    const div = document.createElement('div');
                    div.className = 'listing mgb-1';
                    div.innerHTML = data[i].title;
                    content.appendChild(div);

                    // have to create, add lots of divs and classes
                }

            }
        })
    })

我想知道是否有办法将 Ajax 请求数据作为模板变量发送?还是我必须使用 Javascript 对所有 HTML 标签进行硬编码?

编辑:根据第一个答案创建单独的 HTML 编辑内容。

def search(request):
    ...
    lst = list()

    for listing in queryset:
        ser = ListingSerializer(listing)
        lst.append(ser.data)
    
    return render(request, 'listing/newHtmlFile.html', {'listings': json.dumps(lst)})

单独的 HTML:

{% for list in listings %}
<div class="jumbotron">
    <h1>{{ list.title }}</h1>
</div>
{% endfor %}

和ajax请求:

success: function (response) {
    document.querySelector('#content').insertAdjacentHTML('beforeend', response);
}

【问题讨论】:

  • 不确定成功函数中响应、列表和数据之间的关系...
  • 我不确定,但服务器发送的响应不是在成功函数中处理
  • 当然,但是,您似乎没有对响应做任何事情,而是在迭代一个名为 data 的变量,该变量未在任何地方定义...
  • 刚刚编辑了答案,我不得不迭代response变量

标签: python django ajax


【解决方案1】:

是的,你可以。基本上,这个想法是制作一个单独的 HTML 文件,该文件将由处理 AJAX 请求的视图呈现。然后,您可以使用 JavaScript 和 insertAdjacentHTML() 函数将其插入到您的原始 HTML 文件中。

看看这个例子:

查看:

def ajax_handler(request):
    # ... logic
    return render(request, 'newHtmlFile.html', {'your_context': data})

原始 HTML 文件

<div id='container'>
    
</div>

newHtmlFile.html

<p>{{ your_context }}</p>

JavaScript 部分在这个例子中我使用 Vanilla,而不是 JQuery

let ajax = new XMLHttpRequest();
ajax.onreadystatechange = function(){
    if (this.readyState === 4){
        if (this.status === 200){
            document.querySelector('#container').insertAdjacentHTML('beforeend', this.responseText);
        }
    }
}
ajax.open('GET', '/ajax-handler-url', true);
ajax.send();

如果您有兴趣了解它的工作原理,我们可以将其分解如下:

  1. 您的视图中有一些数据(例如查询集)
  2. 您调用render() 方法并将该数据作为上下文数据传递给模板
  3. render() 方法的实际作用是(让我在这里多余)渲染一个 HTML 文件(将 HTML 本身与您传递的上下文数据相结合)并返回一个包含渲染文本的 HTTPResponse 对象。李>
  4. 呈现的文本(它是一个表示呈现的 HTML 内容的字节串)作为对客户端的响应。在这种情况下,它专门提供给发出请求的 $.ajax() 函数。
  5. 我们使用insertAdjacentHTML() 函数将该呈现的文本附加到所需的元素(在上面的示例中为#container div)。

【讨论】:

  • 你能看看更新的答案吗?我在那里做错了什么
  • 请检查我的更新答案,我做错了什么,我没有得到预期的输出
  • 不是传递 JSON 格式的字符串 (json.dumps(lst)),而是传递列表对象 (lst)。您的上下文数据应为:{'listings': lst}
  • 是的,这个解决方案很棒,我需要你的帮助 &lt;a href="{{ list.get_absolute_url }}" &gt;View Details&lt;/a&gt;img src="{{ list.thumbnail.url }}" &gt; 不起作用。当我检查它时它显示&lt;a href&gt;View Details&lt;/a&gt;,当我检查图像时它显示&lt;img src=(unknown)&gt;。请就这个。
  • 嗯,很难用这么少的信息来判断 listings 列表的内容,但我想说你应该传递你在视图中的查询集 (queryset) ,而不是模板列表,因为您似乎正在尝试访问某些模型的方法
【解决方案2】:

一种快速且可能“肮脏”的方法是在 javascript 中使用反引号字符串:

success: function (r) {
    const listings = JSON.parse(r);  // with the correct headers from django, this should't be needed.
    listings.forEach(e => $('#content').append(`
        <div class="listing mgb-1">${e.title}</div>
    `));
}

您应该使用适当的标头从 django 返回数据,这样您就可以自动获取 json 而不需要eval(response)

【讨论】:

  • 你必须弄清楚数据是什么(也许它应该只是 r.forEach(...),即迭代来自 django 的响应。
  • 我在那里打错字了,我应该遍历listings变量
  • 您能说一下为什么在使用模板文字时将其称为dirty 解决方案吗?
  • 我想它不是特别脏。通过字符串连接构造 html 通常不受欢迎,因为它相对较慢且非常难看(难以阅读)。模板文字不受这些问题的影响,因此它们可能还不错,这只是我历史性的下意识反应;-)
  • 模板标签由 django 评估,它将生成的 html 发送到浏览器。 IE。你不能使用来自 javascript 的 django 模板标签。您可以在 django 中使用 reverse('listing:wishlist') 并将生成的 url 作为 json 响应的一部分传递。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 2018-10-04
  • 2021-10-26
相关资源
最近更新 更多