我一直在努力解决这个问题,并且无法在线找到任何有用的信息。 我想要做的是使用下拉菜单过滤它们并通过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变量被填充并传递给paginator,一切都按预期工作。我得到一定数量的页面,可以浏览页面。现在假设我们再次出现在主页上,然后从下拉菜单中选择“所有时间”。这将触发onchange回调,它将调用FilterCategories()函数。请注意,AJAX中的url是“”(空字符串,因此指向我的索引页)。根据urls.py,它将调用我的entry_index()视图。因为request是ajax,所以使用的模板会更改(page_template成为新模板,page_template = entry_index_page.html)。因为使用下拉菜单指定并使用ajax传递的新时间范围,我得到一个新的obj_list,然后对其进行分页并生成“对象”,然后将其作为上下文传递到模板上。到目前为止,一切都按预期工作。我得到了正确数量的页面等。但是,当我尝试使用新选择的过滤器转到下一页时,问题就出现了。当我单击下一页按钮时,正在进行的请求不是ajax请求,因此不执行request.is_ajax()条件中的所有内容。换句话说,点击下一页再次调用我的entry_index视图,这次使用的模板是entry_index.html,我的过滤器重置为默认值,即“最后24小时”过滤器。因此,当我单击下一页时,我最终得到的实际上是默认主页,而不是使用我新选择的下拉过滤器获取下一页对象。
我的问题是,是否有一种简单的方法可以解决这个问题,以便我可以滚动浏览过滤模型的页面?或者我应该完全放弃这种方法,还有一种更简单的方法吗?我为一篇很长的帖子道歉,我希望那里的人能够帮助我。感谢您抽出宝贵时间阅读本文。
答案 0 :(得分:1)
以下是我使用Django和Ajax在页面上显示动态内容的方法示例:
我正在制作一个小型浏览器科幻游戏,只是为了练习这种特定的技术。一切都在一个视图中发生:
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
属性确定的新数据。
我通过更改数据库中的状态来解决这个问题,但它可以通过会话变量轻松完成。我发现它是一种相对清洁和干燥的循环动态内容方式。它还具有为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-->
此数据直接通过模型管理器的视图提供:
def tile_data(self, status, first, last):
return self.model.objects.filter(status=status)[first:last]