在不重新加载Django中的页面的情况下更新DOM

时间:2017-08-27 16:04:39

标签: python django

我在DOM中有两个选项列表,当视图中的方法加载页面时,首先在加载URL时填充。第二个选项列表的内容取决于用户在第一个选项列表中选择的内容。 当用户在第一个选项列表中进行选择时,如何将python方法绑定到事件,在python中进行一些操作,返回我想在第二个选项列表中显示的vallues列表,然后填充它而不刷新页面?

我的模板如下所示:

{% block content %}

{% if list_of_events %}
    <form>
        <select>
            {% for event in list_of_events %}
                <option value="name">{{ event.module }}</option>
            {% endfor %}
        </select>
    </form>

{% else %}
    <p>No events available now.</p>
{% endif %}

下一个条件是等待first_selection参数,该参数应该在用户选择第一个选项列表中的值后返回到模板。

{% if first_selection %}
    <form>
        <select>
            {% for room in list_of_rooms %}
                <option value="name">{{ room.id }}</option>
            {% endfor %}
        </select>
    </form>
{% endif %}

<input type="submit" value="Submit">

{% endblock %}

我的views.py方法如下所示:

def events(request):
try:
    list_of_events = Event.objects.all()
except:
    raise Http404('Something\'s wrong with events page loader')
return render(request, 'web_service/schedule.html', {
    'list_of_events': list_of_events

})

3 个答案:

答案 0 :(得分:5)

在Django中(至少现在)没有直接的方法可以直接从模板(html)动态调用python方法而不刷新页面。

要调用python方法并在模板中查看它的效果而不刷新页面,则需要JS。它不像在OOP中那样简单地调用实例方法,但并不像看起来那么难。

以下示例演示了如何回复按钮click并将一些数据发送到django view,然后将结果返回到模板而不刷新DOM

从模板调用python代码的唯一方法与我们与url相关的方式相关,这意味着我们必须创建新的url pattern。然后调用必要的view并将模板的响应作为JsonResponse返回。

注意:请务必在jquery代码的内部底部导入<body>

首先,我们需要创建响应器,它将处理按钮点击并创建AJAX请求连接到view的网址。 AJAX requestinput作为参数传递给我们的网址格式,这意味着此参数将传递给django view。如果某些内容从我们对view的调用中返回,那么数据将在success闭包中解压缩。

假设我们的模板如下所示:

<input type="text" id="user-input" autofocus=""><br>
<button type="button" id="sender">Send data</button><br>
<p id="p-text">foo bar</p>

脚本处理点击和请求如下所示:

<script>

$("#sender").click(function () {
    var input = $('#user-input').val();

    $.ajax({
        url: '{% url 'get_response' %}',
        data: {
          'inputValue': input
        },
        dataType: 'json',
        success: function (data) {
          document.getElementById('p-text').innerHTML = data["respond"];
        }
      });
    });

</script>

urls.py中需要新模式:

urlpatterns = [
    ...
    url(r'^ajax/get_response/$', views.answer_me, name='get_response')
    ...
]

注意: url的ajax/部分和url模式的路径本身不会影响此调用的处理方式。它可以是您想要的任何内容,例如:^foo/bar/$

最后一步是添加响应Django view。这个简单的示例返回带有一些附加文本的输入,但通常这是您可以调用其他python方法并执行任何操作的地方:

def answer_me(request):
    field = request.GET.get('inputValue')
    answer = 'You typed: ' + field

    data = {
        'respond': answer
            }
    return JsonResponse(data)

答案 1 :(得分:1)

您可以使用display = none呈现所有可能的第二个选项列表,然后您可以添加如下的JavaScript:

function show(select_item) {
        if (select_item == "apple") {
            hiddenDiv.style.visibility='visible';
            hiddenDiv.style.display='block';
            Form.fileURL.focus();
        } 
        else{
            hiddenDiv.style.visibility='hidden';
            hiddenDiv.style.display='none';
        }
    }   
</script>  

<form>
<label>Fruit:</label>
    <select name="Fruit" onchange="java_script_:show(this.options[this.selectedIndex].value)">
        <option value='pear'>pear</option>
        <option value='apple'>apple</option>
        <option value='grapes'>grapes</option>
    </select>

<div id='hiddenDiv' style="display: none;">
    <label>Are you sure you want to eat the apple?</label>
    <select name="AppleQuestion">
        <option value='Yes'>Yes</option>
        <option value='No'>No</option>
    </select>
</div>
</form>

https://codepen.io/metrafull2/pen/WEgWLo在这里试试

答案 2 :(得分:1)

我有一个与OP类似的问题(公认的答案是我能找到的最接近我的想法),这是我的Google搜索的热门话题,所以我将分享我的想法。 / p>

主要区别是我将dataType设置为'html',并将渲染的模板直接附加到元素上。 (如果您不更改dataType,您将最终会遇到例外情况-无法按照我实施的方式进行操作)

//parent_template.html
{% load static %}
<script src="{% static "jquery.js" %}"></script>

{% block first %}
<div class="row">
    {% for x in my_list %}
    <button class="some-filter" id="{{x}}"></button>
    {% endfor %}
</div>
{% endblock first %}

{% block second %}
<div class="row" id="some_id"></div>
{% endblock second %}

<script>
     $(".some-filter").on({
       click: e=> {
           var name = $( e.target )[0].id;
           $.ajax({
             url: '/ajax/info_getter/',
             data: {
               'name': name,
             },
             dataType: 'html',
             success: function (data) {
               if (data) {
                 $("#some_id").html(data);
                 $(".some-filter").removeClass('selected');
                 $( e.target ).addClass('selected');
               }
             }
           });
       }
   })
</script>



// child_template.html
// my big ass template containing lots of image files
{% load static %}
...other stuff

// urls.py
from django.urls import path
from . import views
urlpatterns = [
    ...
    path('ajax/info_getter/', views.info_getter, name='info_getter'),
    ...
]



// views.py
from django.shortcuts import render
...
def info_getter(request):
    name = request.GET.get('name', None)
    if name:
        context["name"] = name

    response = render(request, "child_template.html", context=context)
    return response

注意:我不确定这是否被视为最佳做法

注意:仅在Django 2.2和Python 3.6.x上进行了测试