Evgenii Legotckoi
Evgenii Legotckoi08 січня 2018 р. 02:52

Django - Підручник 031. Змініть URL-адресу без перезавантаження сторінки з частковим завантаженням вмісту

Що менше інформації доводиться передавати сайту на кожен запит, то краще. Оскільки отримуємо менше навантаження на сервер і канал зв'язку. Першим таким покращенням на сайті я зробив підвантаження списку статей під час навігації по пагінатору сторінок.

Сенс у тому, що коли користувач хоче перейти на наступну сторінку зі списком статей і кликає на посилання в пагінаторі , то відбувається перехоплення події кліка, подія скасовується, але надсилається AJAX запит на сервер з номером сторінки, що запитується. Коли сервер отримує такий запит, він робить рендеринг лише списку статей і надсилає його назад.


Заміна URL у браузері без перезавантаження сторінки

Для головної сторінки сайту я створив JavaScript файл index.js, у якому буде логіка AJAX запиту, а також прив'язка обробника кліку за посиланнями в пагінаторі. Важливим моментом є те, що я використовую для пагінатора django-bootstrap3 . Щоб підключити обробник кліка, я використовую селектор '.paginator > li > a' .

Вміст файлу буде наступним

class Index {

    static initPaginator() {
        document.body.querySelectorAll('.pagination > li > a')
                .forEach( link => link.addEventListener('click', Index.pagination_link_clickHandler) );
    }

    static pagination_link_clickHandler(event){
        event.preventDefault(); // запрещаем событие

        let path = event.target.href; // забираем путь
        let page = Global.getURLParameter(path, 'page');

        if (typeof page !== 'undefined') {
            jQuery.ajax({
                url: jQuery(this).attr('action'),
                type: 'POST',
                data: {'page': getURLParameter(path, 'page')}, // забираем номер страницы, которую нужно отобразить

                success : function (json) {
                    // Если запрос прошёл успешно и сайт вернул результат
                    if (json.result)
                    {
                        window.history.pushState({route: path}, "EVILEG", path); // устанавливаем URL в строку браузера
                        jQuery("#articles-list").replaceWith(articles); // Заменяем div со списком статей на новый
                        Index.initPaginator(); // Переинициализируем пагинатор
                        jQuery(window).scrollTop(0); // Скроллим страницу в начало
                    }
                }
            });
        }
    }
}

Index.initPaginator();

Я намагаюся використовувати стандарт ecmascript 6. Тому для сторінки index використовується клас Index для узагальнення методів, що застосовуються.

Для отримання номера сторінки в URL використовуємо функцію getURLParameter .

Структура шаблонів

Таким чином, у нас має бути спеціальна структура шаблонів, а саме, має бути шаблон для рендерингу списку статей, у моєму випадку шаблон з попередньою статтею, а також шаблон головної сторінки сайту.

Тобто буде:

  • article_preview.html - цей шаблон розглядати не будемо, оскільки він не цікавий для нас у цьому випадку
  • article_previews_list.html
  • index.html

index.html

index.html успадкований від базового шаблону base.html , в якому є блок для підключення javascript файлів.

{% extends 'base.html' %}
{% block page %}
    {% include 'article_previews_list.html' %}
{% endblock %}
{% block javascript_footer %}
    <script src="/static/js/index.js"></script>
{% endblock %}

article_previews_list.html

Список статей є div , який замінюватиметься при кожному запиті.

<div id="articles-list">
    {% load bootstrap_pagination from bootstrap3 %}
    {% for article in object_list %}
        {% include 'knowledge/article_preview.html' %}
    {% endfor %}
    {% bootstrap_pagination object_list pages_to_show="10" %}
</div>

urls.py

Маршрут для головної сторінки буде виглядати так

urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index')
]

views.py

А тепер розглянемо уявлення, яке повертатиме список статей або одразу всю сторінку

class IndexView(View):
    template_name = 'index.html'

    def get(self, request):
        return render(request=request, template_name=self.template_name, context={'object_list': get_paginated_page(request, Article.objects.all())})

    def post(self, request):
        if request.is_ajax():
            return JsonResponse({
                "result": True,
                "articles": render_to_string(
                    request=request,
                    template_name='article_previews_list.html',
                    context={'object_list': get_paginated_page(request, Article.objects.all())}
                )
            })
        else:
            raise Http404()

Важливим моментом є те, що сайт повинен коректно обробляти обидва види запитів як звичайний, так і AJAX запит. Оскільки користувач може зайти безпосередньо на одну зі сторінок, так і за допомогою пагінації на сайті.

Можливо, вас в даному коді зацікавить метод get_paginated_page, який за допомогою класу Paginator генерує потрібну сторінку для відображення.

# -*- coding: utf-8 -*-

from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage


def get_paginated_page(request, objects, number=10):
    current_page = Paginator(objects, number)
    page = request.GET.get('page') if request.method == 'GET' else request.POST.get('page')
    try:
        return current_page.page(page)
    except PageNotAnInteger:
        return current_page.page(1)
    except EmptyPage:
        return current_page.page(current_page.num_pages)

Для Django рекомендую VDS-сервера хостера Timeweb .

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

B
  • 24 лютого 2020 р. 00:37

Евгений Здравствуйте! Не могу понять вот эту часть кода: url: jQuery(this).attr('action')
наверное здесь должен быть путь к url, тогда 'action' на какой url указывает?

Evgenii Legotckoi
  • 24 лютого 2020 р. 03:54

Добрый день. Там будет url, на который указывает ссылка тега a в пагинаторе, если правильно помню )) Написал этот код и забыл.

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 08:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 08:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
i
innorwall14 листопада 2024 р. 19:42
Як скопіювати файли в Linux If only females relatives with DZ offspring were considered these percentages were 23 order priligy online uk
i
innorwall14 листопада 2024 р. 17:09
Qt/C++ - Підручник 068. Hello World за допомогою системи збирання CMAKE в CLion ditropan pristiq dosing With the Yankees leading, 4 3, Rivera jogged in from the bullpen to a standing ovation as he prepared for his final appearance in Chicago buy priligy pakistan
i
innorwall14 листопада 2024 р. 12:05
EVILEG-CORE. Використання Google reCAPTCHA 2001; 98 29 34 priligy buy
i
innorwall14 листопада 2024 р. 12:00
PyQt5 - Урок 007. Працює з QML QtQuick (Сигнали та слоти) priligy 30mg Am J Obstet Gynecol 171 1488 505
Тепер обговоріть на форумі
i
innorwall14 листопада 2024 р. 11:39
добавить qlineseries в функции priligy amazon canada 93 GREB1 protein GREB1 AB011147 6
i
innorwall11 листопада 2024 р. 18:55
Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
9
9Anonim25 жовтня 2024 р. 16:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
ИМ
Игорь Максимов03 жовтня 2024 р. 11:05
Реализация навигации по разделам Спасибо Евгений!

Слідкуйте за нами в соціальних мережах