几天来我一直在努力解决这个问题,但无法在线找到任何有用的信息。 我想要做的是在使用下拉菜单过滤对象并通过 AJAX 将数据提供给 python 后对模型中的对象进行分页。我知道问题出在哪里,但我不确定如何解决。我有两个模板,第一个是:
entry_index.html:
{% extends 'main/base.html' %}
<form action="" method="get" accept-charset="utf-8">
<select class="selectpicker" name="times" onchange="FilterCategories()" id="times">
<option value="1">last 24 hours</option>
<option value="30">past month</option>
<option value="365">past year</option>
<option value="10000">all time</option>
</select>
</form>
<ul id="all-games" class="list-unstyled">
{% include page_template %}
</ul>
上述模板中包含的模板是entry_index_page.html:
{% if objects %}
{% for object in objects %}
do something
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if objects.has_previous %}
<a href="?page={{ objects.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ objects.number }} of {{ objects.paginator.num_pages }}.
</span>
{% if objects.has_next %}
<a href="?page={{ objects.next_page_number }}">next</a>
{% endif %}
</span>
</div>
urls.py:
url(r'^$', views.entry_index, name='index')
views.py:
def entry_index(
request,
template='entry_index.html',
page_template='entry_index_page.html'):
date_from = timezone.now() - timezone.timedelta(days=1)
obj_list=Object.objects.filter(submitted__gte = date_from).order_by('-votes')
message=[]
context = {
'objects': obj_list,
'page_template': page_template}
if request.is_ajax():
template = page_template
message = []
if request.method == "GET":
time_range = request.GET.get('time_range')
if time_range is not None and time_range != u"":
time_range = request.GET['time_range']
date_from = timezone.now() - timezone.timedelta(days=int(time_range))
obj_list= Object.objects.filter.filter(submitted__gte=date_from)
paginator = Paginator(obj_list, 2)
page = request.GET.get('page')
try:
objects= paginator.page(page)
except PageNotAnInteger:
objects= paginator.page(1)
except EmptyPage:
objects= paginator.page(paginator.num_pages)
context.update({"message":message,"objects":objects})
return render_to_response(
template, context, context_instance=RequestContext(request))
ajax.js:
function FilterCategories() {
var timePosted = document.getElementById('times');
$.ajax({
type: "GET",
url: "",
data: {
'time_range': timePosted.value,
'csrfmiddlewaretoken': $("input[csrfmiddlewaretoken]").val()
},
success: filterResults,
dataType: 'html'
});
}
现在解释我的想法,希望有人能帮助我找到解决方案。
加载主页 (entry_index.html) 时,模型将根据下拉菜单中的第一个选项进行过滤(即 value="1",这是针对最后一天内提交的数据条目进行过滤)。 obj_list 变量被填充并传递给分页器,一切都按预期进行。我得到一定数量的页面并且可以浏览页面。现在让我们假设我们再次回到主页,我从下拉菜单中选择“所有时间”。这将触发 onchange 回调并调用 FilterCategories() 函数。请注意 AJAX 中的 url 是“”(一个空字符串,因此指向我的索引页面)。根据 urls.py,它将调用我的 entry_index() View 。因为request是ajax,所以使用的模板会变(page_template变成新的模板,page_template = entry_index_page.html)。因为使用下拉菜单指定的新时间范围并使用 ajax 传递,所以我得到一个新的 obj_list,然后对其进行分页并生成“对象”,然后将其作为上下文传递到模板上。到目前为止,一切都按预期进行。我得到了适量的页面等。但是,当我尝试使用新选择的过滤器转到下一页时,问题就开始了。当我单击下一页按钮时,发出的请求不是 ajax 请求,因此 request.is_ajax() 条件中的所有内容都不会执行。所以换句话说,点击下一页会再次调用我的 entry_index View ,这次使用的模板是 entry_index.html,我的过滤器被重置为默认值,即“过去 24 小时”过滤器。因此,当我单击下一页时,我最终得到的实际上是默认主页,而不是使用新选择的下拉过滤器获取下一页对象。
我的问题是,是否有一种简单的方法可以解决此问题,以便我可以滚动浏览已过滤模型的页面?或者我应该完全放弃这种方法并且有更简单的方法来做到这一点?我为一篇很长的帖子道歉,我希望有人能够帮助我。感谢您花时间阅读本文。
请您参考如下方法:
下面是我使用 Django 和 Ajax 在页面上显示动态内容的方法示例:
我正在制作一个小型浏览器科幻游戏来练习这项特定技术。一切都发生在一个 View 中:
class GameViewport(TemplateView):
template_name = "game_viewport.html"
@cached_property
def slug(self):
return self.kwargs['slug']
@cached_property
def game(self):
return Game.objects.get(url=self.kwargs['slug'])
@cached_property
def player(self):
return Player.objects.get(game=self.game)
@cached_property
def current_planet(self):
return self.player.current_planet
@cached_property
def left_column(self):
player = self.player
if player.current_location:
node = player.current_node
if len(Location.objects.filter(node=node)) == 0:
spawn_locations(node)
locations = Location.objects.filter(node=node)
else:
locations = Location.objects.filter(planet=node)
html = "Other Sites in ".format(str(node))
for location in locations:
html += '<li><a href="" class="locationChoice"></a>{} ({})</li>'.format(location.name, location.type.name)
return html
elif player.current_node:
planet = player.current_planet
if len(Node.objects.filter(planet=planet)) == 0:
spawn_nodes(planet, get_name_choices())
nodes = Node.objects.filter(planet=planet)
else:
nodes = Node.objects.filter(planet=planet)
html = '<h4><b>Other Starports on {}:</b></h4>'.format(planet.name)
for node in nodes:
html += '<li><a href="" class="nodeChoice"> {} </a> ({})</li>'.format(node.name, node.type.name)
return html
elif player.current_planet:
system = player.current_system
html = '<h4><b>Known Planets in {}:</b></h4>'.format(system.name)
for known_planet in player.known_planets.filter(solar_system=system):
html += '<li><a href="" class="planetChoice"> {} </a> ({})</li>'.format(
known_planet.name,
known_planet.classification.name
)
return html
else:
html = '<h4><bShip Status</b></h4>'
html += '<p><b>Fuel:</b> 100%</p>'
return html
如您所见,左侧栏会根据播放器的当前设置生成不同的 html 数据。这将像这样插入到模板中:
<div class="col-md-3">
<div class="leftColumn">
{% autoescape off %}
{{ view.left_column }}
{% endautoescape %}
</div>
</div>
<a href="{% url "visit_planet" view.slug %}" id="visitPlanet"></a>
如果用户点击新位置,我会通过 AJAX 发送她的决定:
$(".planetChoice").click(function(){
event.preventDefault();
var submission_data = {planet: $(this).text()};
console.log(submission_data);
$.ajax({
url: $('#visitPlanet').attr('href'),
type: 'GET',
dataType: "json",
data: submission_data,
success: function(html_data) {
window.location.reload();
},
failure: function(data) {
alert('Something went wrong. Please refresh the page.');
}
});
});
所有这一切都会根据她的新设置更新播放器的状态并重新加载页面:
def visit_planet(request, slug):
player = Game.objects.get(url=slug).player_1
planet = Planet.objects.get(name=request.GET.get('planet', "").strip())
if planet:
player.current_location = None
player.current_node = None
player.current_planet = planet
player.save()
response = {'status': 1, 'message': "Ok"}
return JsonResponse(response)
从而显示由 left_column 属性确定的新数据。
我通过更改数据库中的状态来解决这个问题,但它可以通过 session 变量轻松完成。我发现它是一种相对干净和干燥的循环动态内容的方式。它还具有让 Django 有机会在点击之间生成或修改数据的优势。
不确定这是否适用于您的情况,但希望它能激发您的灵感!
编辑:您甚至不一定需要输出 HTML。这是我在不同应用程序中使用的方法:
<!--Product Tile #1-->
{% if view.tile_data.0 %}
<div class="col-md-4">
<div class="card hoverable">
<!--Card content-->
<div class="card-block" id="tile_{{ view.tile_data.0.invoice }}_id">
<!--Title-->
<h4 class="card-title">Shipment {{ view.tile_data.0.invoice }}</h4>
<!--Text-->
<p class="card-text">{{ view.tile_data.0.supplier.name }}
<br>
<b>{{ view.tile_data.0.lbs|floatformat }} Lbs @ {{ view.tile_data.0.price }} USD</b>
<br>
{{ view.tile_data.0.variety.commodity }} {{ view.tile_data.0.variety }} {{ view.tile_data.0.inshell|shell_display }}</p>
</div>
<!--/.Card content-->
</div>
</div>
{% endif %}
<!--./Product Tile #1-->
此数据直接通过模型管理器的 View 提供:
def tile_data(self, status, first, last):
return self.model.objects.filter(status=status)[first:last]
