【问题标题】:Ajax Triggered request doesn't update Django ViewAjax 触发请求不更新 Django 视图
【发布时间】:2020-02-27 00:12:33
【问题描述】:

我试图把这个问题分解成最简单的例子。当请求是 ajax 时,使用更新的上下文渲染页面不会产生预期的结果。

index.html:

<html>
    <body>
        {% if templateVariable %}
            <h1>{{ templateVariable }}</h1>
        {% endif %}

        <button id="testBtn">TEST</button>

        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> 
        <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
        <script type="text/javascript">

            $(document).ready(function() {
                $(function() {
                    $('#testBtn').click(function(event) {
                        $.ajax({
                            type: "POST",
                            url: "./",
                            data: {
                                'x' : 'x',
                                'csrfmiddlewaretoken' : '{{ csrf_token }}'
                            }
                        });
                    });
                });
            });

        </script>
    </body>
</html>

views.py

def index(request):
    context = {}
    if 'x' in request.POST:
        context['templateVariable'] = 'I was updated via ajax'
        print('ajax ran')
        return render(request, 'index.html', context)
    context['templateVariable'] = 'I was not updated via ajax'
    print('ajax was not run')
    return render(request, 'index.html', context)
  • 当我第一次加载页面时,'ajax was not run' 被打印,templateVariable 是'我没有通过 ajax 更新',并且页面按预期在 h1 标记中呈现。

  • 当我单击 testBtn 时,我希望 ajax 请求触发 if 语句,更新上下文,并在 h1 标记中使用“I was updated by ajax”呈现页面。

  • 相反,打印了“ajax ran”,但在呈现页面时,templateVariable 仍然是“I was not updated by ajax”。 'ajax was not run' 仅在页面最初加载时打印一次。

为什么我没有得到预期的结果?

编辑:似乎每个人都同意您不能使用 ajax 请求返回渲染和更新上下文变量,但我仍然遇到问题,因为我相信这是可能的。这是一些替代代码:

index2.html:

<html>
    <body>
        {% if templateVariable %}
            <h1>{{ templateVariable }}</h1>
        {% endif %}

        <h1 id="placeHolder"></h1>

        <button id="testBtn">TEST</button>

        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> 
        <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
        <script type="text/javascript">

            $(document).ready(function() {
                $(function() {
                    $('#testBtn').click(function(event) {
                        $.ajax({
                            type: "POST",
                            url: "./",
                            data: {
                                'x' : 'x',
                                'csrfmiddlewaretoken' : '{{ csrf_token }}'
                            },
                            success: function (data) {
                                $('#placeHolder').html(data);
                            },
                            dataType: 'html'
                        });
                    });
                });
            });

        </script>
    </body>
</html>

views2.py

def index2(request):
    context = {}
    if 'x' in request.POST:
        context['templateVariable'] = 'I was updated via ajax'
        print('ajax ran')
        return render_to_response('notIndex.html', context)
    context['templateVariable'] = 'I was not updated via ajax'
    print('ajax was not run')
    return render(request, 'index.html', context)

notIndex.html:

{% if templateVariable %}
    {{ templateVariable }}
{% endif %}
  • 在此示例中,页面最初在上下文中使用 templateVariable 加载为“我没有通过 ajax 更新”。
  • 点击 testBtn 时,ajax 请求会触发视图中的 if 块。这会使用更新的上下文呈现 notIndex.html。
  • ajax调用成功函数将生成的html从notIndex.html设置为h1标签。

那么,如果页面与 ajax 调用来自的页面不同,为什么只能使用 ajax 触发页面呈现?

【问题讨论】:

  • 因为使用 ajax 意味着您不会在浏览器中刷新整个页面,这意味着页面不会被 Django (重新)渲染,因此不会被更新。要使用来自 ajax 请求的数据更新页面,您必须自己使用 javascript 更新 html。
  • index.html 中的if 在页面首次加载时被评估。如果您想在加载页面后更改某些内容。你不能用 django-template 做到这一点。您必须使用 JavaScript 来做到这一点。
  • 似乎传统的方法是使用更新的上下文渲染另一个页面,并将 index.html 上的某个占位符对象的 innerHTML 设置为在成功/完成函数中在该其他页面上生成的 html。在这种情况下,每次调用 render 时都会更新其他页面的上下文。那么为什么在渲染同一个页面时上下文不会更新呢?
  • 因为您已经明确告诉浏览器不要选择使用Ajax。这就是重点。

标签: django ajax


【解决方案1】:

你不能从 AJAX 返回渲染或重定向,这就是它的工作原理

如果您想根据服务器上发生的事情更新您的 UI,比如您有一个购物车,并且您想在不刷新页面的情况下实现“添加到购物车”,则“添加到购物车”按钮必须请求您在urls.py 中提供的端点 & 如果添加了对象,该 url 必须返回 true,否则返回 false,但它不会在 UI 上更新它,您需要使用 Javascript 手动更改购物车项目数。

如果您尝试将渲染重定向或返回到 ajax,它将获取 HTML 或重定向/渲染,仅此而已。

如果你想重定向,你会想用 JS 来做,但没有来自 django 的上下文变量。

看到这个ref

【讨论】:

  • 如果 ajax 请求触发了一个视图函数,该视图函数呈现一个带有一些上下文变量的备用 html 页面,情况会怎样。在 ajax 成功函数中,您将原始页面上的占位符对象的 html 设置为返回的数据(应该是备用页面的 html)。在这种情况下,每次进行 ajax 调用时,render() 都会返回更新的上下文变量。但是尝试使用更新的上下文变量呈现原始页面不起作用?这就是我感到困惑的地方
  • 这很令人困惑,因为你不能返回渲染或重定向到 ajax,你应该只返回响应,如果我理解正确,这是因为当你对端点进行 ajax 调用时,端点调用它类视图或函数 & 执行内部代码,直到它返回渲染,它实际上返回渲染,但它不能被渲染,因为这不是 ajax 的工作方式,如果你问其他问题,请随时解释你不这样做'不懂
  • 不可能触发渲染,无论是渲染同一个页面还是另一个页面,但是你通过return render()收到页面的HTML,你可以做任何你想做的事与 HTML
  • 顺便说一句,使用 ajax 时,不要对任何字典中的任何键进行字符串化,所以你应该发布 csrfmiddlewaretoken : 'csrfmiddlewaretoken'
  • and x: 'x' not 'x': 'x'
猜你喜欢
  • 1970-01-01
  • 2020-03-03
  • 2020-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-02
  • 1970-01-01
  • 2015-10-16
相关资源
最近更新 更多