【问题标题】:How to append pages of data using jQuery and Django pagination?如何使用 jQuery 和 Django 分页附加数据页面?
【发布时间】: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_URL}}{{snap.image}}" data-imagelightbox="f"><img src="{{MEDIA_URL}}{{snap.image}}" alt="{{snap.caption}}" /></a></li>
    {% endfor %}
        <span class="clear_both"></span>
    </ul>
{% endfor %}

【问题讨论】:

  • 如果你想使用 Ajax,我个人不会使用 Django 的分页。有很多 JavaScript 寻呼机可以很好地处理从 Django 服务器发送的 JSON 数据。或者,如果您愿意,也可以使用内置分页功能的 Django-Rest-Framework,但通过 ajax 访问端点会更有效。
  • @ChrisHawkes 是的,这样会更好。但是我只是在学习,请你告诉我怎么做。如果我得到我想要的结果,我必须更改代码。

标签: jquery ajax django pagination


【解决方案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)
猜你喜欢
  • 2013-03-11
  • 2013-09-21
  • 2022-12-10
  • 1970-01-01
  • 2019-06-07
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
相关资源
最近更新 更多