exibite777
@exibite777
Ведущий системный аналитик

Как сделать автоматическую загрузку публикаций при прокрутке?

Добрый день комрады! Решил прикрутить на своем пет-проекте крутилку с Ajax для автоматической загрузки публикацию. Вроде грузит, но есть пара проблем, которые никак не могу решить
Кусок шаблона publications.html
<nowrap id="publoader">
    <div class="col-md-12">
        <div class="alert alert-info">
          <div class="clearfix">Загрузка публикаций ...
            <div class="spinner-border float-right" role="status">
              <span class="sr-only">Загрузка публикаций ...</span>
            </div>
          </div>
        </div>
    </div>
    <script type="text/javascript">
        window.addEventListener('scroll', function() {
        let windowRelativeBottom = document.documentElement.getBoundingClientRect().bottom;
        if (windowRelativeBottom < document.documentElement.clientHeight + 100) {
          var myDiv = document.getElementById("publoader");
          $.ajax({
                url: "/mytestblog/ajaxMorePub?cat={{ cat_id_join }}{% if tag.0 != "" %}&tag={{ tagstr_param }}{% endif %}&page={{ page }}&size={{ size }}&order={{ order }}&direction={{ direction }}",
                success: function(data){
                  myDiv.id="pass";
                  myDiv.innerHTML=data;
                                       }
                  });
                                                                                }
        });
    </script>
</nowrap>
Шаблон ajaxMorePub.html (оно же, но с загрузкой контента)
{% include "pubcontent.html" %}
<nowrap id="publoader">
    <div class="col-md-12">
        <div class="alert alert-info">
          <div class="clearfix">Загрузка публикаций ...
            <div class="spinner-border float-right" role="status">
              <span class="sr-only">Загрузка публикаций ...</span>
            </div>
          </div>
        </div>
    </div>
    <script type="text/javascript">
        window.addEventListener('scroll', function() {
        let windowRelativeBottom = document.documentElement.getBoundingClientRect().bottom;
        if (windowRelativeBottom < document.documentElement.clientHeight + 100) {
          var myDiv = document.getElementById("publoader");
          $.ajax({
                url: "/mytestblog/ajaxMorePub?cat={{ cat_id_join }}{% if tag.0 != "" %}&tag={{ tagstr_param }}{% endif %}&page={{ page }}&size={{ size }}&order={{ order }}&direction={{ direction }}",
                success: function(data){
                  myDiv.id="pass";
                  myDiv.innerHTML=data;
                                       }
                  });
                                                                                }
        });
    </script>
</nowrap>

Вьюха, которая обрабатывает оба запроса
def pubcontent(request, template):
    cat_id = request.GET.get("cat", '0')
    tag = request.GET.get("tag", "")
    page = request.GET.get("page", 1)
    order = request.GET.get("order", 'date')
    direction = request.GET.get("direction", 'DESC')
    size = request.GET.get("size", 5)
======================================
    # обработка параметра page
    try: page=int(page)
    except Exception:
        page=1
    if page<1:
        page=1
    if template == "ajaxMorePub.html":
        page += 1 
========================================
# получаем список pub_id по параметрам
    pubidlist=get_pub_id_by_params(cat_id=set(cat_id), tag=set(tag),
                    order=order, direction=direction)
# осуществляем пагинацию
    paginator = Paginator(pubidlist, size)
    if page>paginator.num_pages:
        page=paginator.num_pages
    pubidlist = paginator.get_page(page)
# запрашиваем модель данных
    pubmodel=get_pub_model(pubidlist,
        order=order, direction=direction)
=========================================
    return render(request, template, {
            'categories': catlist,
            'pub_sorted': pubmodel.items(),
            'cat_param': cat_name.replace(", ", ","),
            'cat_name': cat_name,
            'cat_id_join': ",".join(str(elem) for elem in cat_id),
            'cat_id': cat_id,
            'tags': taglist,
            'order': order, 'size': size, 'direction': direction,
            'page_range': paginator.page_range,
            'num_pages': paginator.num_pages,
            'paginator': paginator.page(page),
            'page': page,
            'tagstr_param': tagstr.replace(", ", ","),
            'tagstr_header': tagstr,
            'tag':tag
        })


def publications(request):
    pub_content = pubcontent(request, template="publications.html")
    return pub_content

def ajaxMorePub(request):
    pub_content = pubcontent(request, template="ajaxMorePub.html")
    return pub_content

Лишние куски удалил, местами костыли, но так надо :-) По коду видно, что вьюха инкрементит страницу для шаблона ajaxMorePub.html.

Что имеем в итоге: страница загружается, пролистываем до крутилки, успешно загружается вторая страница. А вот дальше приколы
Проблема №1. Крутилка почему-то каждый раз загружает вторую страницу, не двигается вперед. Если открыть в браузере прям страницу /mytestblog/ajaxMorePub/?cat=0&page=1&size=5&order=date&direction=DESC то видно, что вьюха отрабатывает, есть контент второй страницы, в скрипте честно написано /mytestblog/ajaxMorePub/?cat=0&page=2&size=5&order=date&direction=DESC (ну то есть типа в следующий раз отдаст третью страницу)
Но когда это все возвращается /mytestblog/publication/ то при вставке myDiv.innerHTML=data контент второй страницы загружается, а вот скрипт почему-то нет, в нем так и остается /mytestblog/ajaxMorePub/?cat=0&page=1&size=5&order=date&direction=DESС. В итоге ходим по кругу
Проблема №2. Собственно сама прокрутка многократно дергает ajaxMorePub.html, это видно по консоли Django. Как сделать, чтобы дергало один раз за одну загрузку?
  • Вопрос задан
  • 182 просмотра
Решения вопроса 1
exibite777
@exibite777 Автор вопроса
Ведущий системный аналитик
Решилось следующим образом
Кусок шаблона publication.html
{% block сontent %}
    <nowrap id="contentBlock">
        {% include "pubcontent.html" %}
    </nowrap>
    <div class="col-md-12">
        <div class="alert alert-info">
          <div class="clearfix">Загрузка публикаций ...
            <div class="spinner-border float-right" role="status">
              <span class="sr-only">Загрузка публикаций ...</span>
            </div>
          </div>
        </div>
    </div>
    <script type="text/javascript">
        window.need_load_more=1;
        window.need_page=2;
        window.addEventListener('scroll', function() {
        let windowRelativeBottom = document.documentElement.getBoundingClientRect().bottom;
        if (windowRelativeBottom < document.documentElement.clientHeight + 100) {
            if (window.need_load_more == 1) {
                window.need_load_more = 0;
            var myDiv = document.getElementById("contentBlock");
            $.ajax({
                url: "/mytestblog/pubcontent?cat={{ cat_id_join }}{% if tag.0 != "" %}&tag={{ tagstr_param }}{% endif %}&page=" + window.need_page + "&size={{ size }}&order={{ order }}&direction={{ direction }}",
                success: function(data){
                  myDiv.insertAdjacentHTML('beforeEnd', data);
                  window.need_page = window.need_page + 1;
                  window.need_load_more = 1;
                                       }
                  });
            };                                                                     }
        });
    </script>
{% endblock %}

1. Скрипт вынес из блока, вместо innerHTML использую insertAdjacentHTML
2. Соответственно отдельного шаблона ajaxMorePub.html не нужно, скрипт использует тот же шаблон pubcontent.html, что и элемент contentBlock, в который этот контент добавляется
3. В url.py соответственно добавилось pubcontent.html
4. Инкрементом теперь занимается скрипт, а не вьюха
5. Глобальный флаг решает проблему множественного запроса
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы