我在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
})
答案 0 :(得分:5)
在Django中(至少现在)没有直接的方法可以直接从模板(html)动态调用python方法而不刷新页面。
要调用python方法并在模板中查看它的效果而不刷新页面,则需要JS
。它不像在OOP中那样简单地调用实例方法,但并不像看起来那么难。
以下示例演示了如何回复按钮click
并将一些数据发送到django view
,然后将结果返回到模板而不刷新DOM
。
从模板调用python代码的唯一方法与我们与url
相关的方式相关,这意味着我们必须创建新的url pattern
。然后调用必要的view
并将模板的响应作为JsonResponse
返回。
注意:请务必在jquery
代码的内部底部导入<body>
。
首先,我们需要创建响应器,它将处理按钮点击并创建AJAX
请求连接到view
的网址。 AJAX request
将input
作为参数传递给我们的网址格式,这意味着此参数将传递给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>
答案 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上进行了测试