如何使用 jQuery 和 Django 分页附加数据页面?
Posted
技术标签:
【中文标题】如何使用 jQuery 和 Django 分页附加数据页面?【英文标题】:How to append pages of data using jQuery and Django pagination? 【发布时间】:2015-09-04 07:09:39 【问题描述】:我正在使用 Django 的内置 pagination
对数据进行分页并在模板中显示。我现在想实现 jQuery 以使用 ajax 加载和附加页面到模板。我如何使用 jQuery 来做到这一点?
我之前使用的是django-endless-pagination,但由于它通过 javascript 添加条目,所以我的灯箱显示图像不会捕获图像元素,只显示在第一次请求时加载的条目。
views.py:
def snaps(request):
snapgroup_list = SnapGroup.objects.all()
paginator = Paginator(snapgroup_list, 1)
try:
page = int(request.GET.get('page', '1'))
except:
page = 1
try:
snapgroup = paginator.page(page)
except(EmptyPage, InvalidPage):
snapgroup = paginator.page(page)
index = snapgroup.number - 1 # edited to something easier without index
max_index = len(paginator.page_range)
start_index = index - 3 if index >= 3 else 0
end_index = index + 3 if index <= max_index - 3 else max_index
page_range = paginator.page_range[start_index:end_index]
return render(request, 'snaps.html',
'page_range': page_range,
'snapgroup':snapgroup
)
snaps.html:
% extends "base.html" %
% block main_content %
<div id="main_content">
<div id="snap_wrapper" class="container">
<hr>
% if snapgroup.object_list.count > 0 %
% include 'snapgroups.html' %
% else %
<li><p>No SNAPS yet!</p></li>
<span class="clear_both"></span>
% endif %
</div>
</div>
<div class="container">
<div class="prev_next">
% if snapgroup.has_previous %
<a class="prev btn btn-info" href="?page=snapgroup.previous_page_number">Prev</a>
% endif %
% if snapgroup.has_next %
<a class="next btn btn-info" href="?page=snapgroup.next_page_number">Next</a>
% endif %
<div class="pages">
<ul>
% for pg in page_range %
% if snapgroup.number == pg %
<li><a href="?page=pg" class="btn btn-default">pg</a></li>
% else %
<li><a href="?page=pg" class="btn">pg</a></li>
% endif %
% endfor %
</ul>
</div>
<span class="clear_both"></span>
</div>
</div>
% endblock %
snapgroups.html:
% for sg in snapgroup.object_list %
<h4 id="combination" class="snap_date">sg.date|date:'l', sg.date</h4>
<ul>
% for snap in sg.snap_set.all %
<li><a href="MEDIA_URLsnap.image" data-imagelightbox="f"><img src="MEDIA_URLsnap.image" /></a></li>
% endfor %
<span class="clear_both"></span>
</ul>
% endfor %
【问题讨论】:
如果你想使用 Ajax,我个人不会使用 Django 的分页。有很多 JavaScript 寻呼机可以很好地处理从 Django 服务器发送的 JSON 数据。或者,如果您愿意,也可以使用内置分页功能的 Django-Rest-Framework,但通过 ajax 访问端点会更有效。 @ChrisHawkes 是的,这样会更好。但是我只是在学习,请你告诉我怎么做。如果我得到我想要的结果,我必须更改代码。 【参考方案1】:我会向您展示一个示例应用程序。由于您只是在学习,如果您真的使用下面的代码制作了一个这样的应用程序,这将很有帮助。
我已尽量减少代码。
models.py
class Article(...):
title = models.CharField(...)
photo = models.ImageField(...)
views.py
import json
def article_ajax(request):
TOTAL = 10
OFFSET = request.GET.get('offset', 0)
END = offset + TOTAL
# TOTAL means how many articles to load
# in a single request
# to understand OFFSET and END, consider this:
# mylist = [1,2,3,4,5,6,7,8,9]
# mylist[2:5] outputs => [3,4,5]
# Above 2 is OFFSET and 5 is END
articles = Article.objects.all()[OFFSET:END]
json_list = []
for article in articles:
json_list.append(
'title': article.title, 'photo_url': article.photo.url
)
data = json.dumps(json_list)
return HttpResponse(data, content_type='application/json')
urls.py
...
url(r'^ajax/articles/$', 'myapp.views.article_ajax'),
...
articles.html
该脚本也包含无限滚动代码:)
<!-- All articles will be loaded in following div -->
<div id="ArticlesDiv"></div>
<script>
var articleOffset = 0;
var articleLoader = function()
$.ajax(
url: '/ajax/articles/?offset=' + articleOffset,
success: function(data)
if (data.length > 0)
for (var i = 0, total = data.length; i < total; i++)
var compile_data;
compile_data = '<h1>' + data[i].title + '</h1>\
<img src="' + data[i]photo_url + '">';
$('#ArticlesDiv').append(compile_data);
/* update the offset */
articleOffset += 10
else
$('#ArticlesDiv').append('No articles found');
);
/* Infinite scrolling for fetching articles */
var $window = $(window);
function prodScrollPosition()
var distance = $window.scrollTop() + $window.height();
if ($('body').height() <= distance && $('#ArticlesDiv'))
articleLoader();
$window.scroll(prodScrollPosition).scroll();
/* Manually initiate the first ajax request */
articleLoader();
</script>
【讨论】:
哇,这太棒了。我只是在通过外键引用_set.all
时如何做到这一点感到困惑。因为在模板中,我循环遍历每个SnapGroup
,然后再次循环遍历一个SnapGroup
中的每个Snap
。我怎么做?请你帮我解决这个问题。谢谢。
@Robin 我认为在一个页面中显示所有SnapGroups
和所有Snaps
不是一个好主意。它对数据库过于密集,如果数据库中的行太多,它会减慢您的应用程序的速度。我建议做的是在一页中显示所有SnapGroups
。然后用户将选择一个SnapGroup
来查看其中的Snaps
。这种方法速度更快,并且不会用不必要的查询访问数据库。
这是一个很好的答案!我唯一需要更改的是执行 JSON.parse(data) 将传入的 JSON 数据转换为 Javascript 对象并从中获取正确的长度(否则我会得到字符数)。【参考方案2】:
我仍然会使用django-endless-pagination(它是目前最好的基于 ajax 的分页插件),您的问题的解决方案是在分页请求完成后调用lightbox
init,阅读更多关于callbacks:
<script type="text/javascript">
function hookup_lightbox()
$( selector ).imageLightbox();
$.endlessPaginate(
onCompleted: function(context, fragment)
// hookup lightbox
hookup_lightbox();
);
</script>
【讨论】:
这个解决方案是更适合原始问题的答案。 (虽然我会建议使用 Django Rest Framework 的解决方案,例如已经提到的@ChrisHawkes)以上是关于如何使用 jQuery 和 Django 分页附加数据页面?的主要内容,如果未能解决你的问题,请参考以下文章