Django - как фильтровать новости по категориям + пагинатор.
Всем привет!
Сегодня расскажу, как я боролся с пагинацией страниц внутри категорий. Была задача сделать категории и отфильтровать все записи блога по категориям + разбиение новостей пагинатором, чтоб к примеру была возможность выводить на одной странице не все записи категории а только к примеру первые 5 и т.д.
Итак приступим.
Создаем модель Category в models.py
class Category(models.Model):
class Meta():
db_table = 'category'
ordering = ['name']
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
name = models.CharField(max_length=150, unique=True, verbose_name='Категория')
slug = models.SlugField(verbose_name='Транслит', null=True)
def __unicode__(self):
return self.name
Пишем функцию - обработчик, которая будет делать фильтровать записи по категориям и выводить пагинатор.
def category(reguest, slug):
category = Category.objects.get(slug=slug)
post = BlogPost.objects.filter(category=category)
paginator = Paginator(post, 2)
page = reguest.GET.get('page')
try:
post = paginator.page(page)
except PageNotAnInteger:
post = paginator.page(1)
except EmptyPage:
post = paginator.page(paginator.num_pages)
return render(reguest, 'category.html', {
'category': category,
'page': page,
'post': post})
Как видим функция принимает два параметра 1 запрос и slug то что мы прописали в модели.
category = Category.objects.get(slug=slug) - Получаем категории из базы данных.
post = BlogPost.objects.filter(category=category) - Получаем записи блога и применяем сразу фильтрацию по категориям. Это означает, если зайти в категорию к примеру Django в которой есть на текущий момент 12 записей, то они все выведутся на странице.
paginator = Paginator(post, 2) - Пишем пагинатор. Вставляем в пагинатор переменную в моем случае это post, которая тянет записи из базы данных и количество 2 - это сколько будет выводится новостей на странице данной категории.
page = reguest.GET.get('page') - Пишем GET запрос по которому будем перебирать новости вперед/назад внутри категории.
Далее пишем такую конструкцию
try: post = paginator.page(page) except PageNotAnInteger: post = paginator.page(1) except EmptyPage: post = paginator.page(paginator.num_pages)
Параметр (1) - это означает с какой записи начинать переход т.е. с первой.
Ну и возвращаем все это дело так.
return render(reguest, 'category.html', { 'category': category, 'page': page, 'post': post})
Теперь напишем урл для этой функции
url(r'^category/(?P<slug>[-\w]+)/$', views.category, name='category'),
Ну и выводим все это дело в шаблон!
<div class="row">
<div class="col-lg-12" align="center">
<ul class="pagination">
{% if post.has_previous %}
<li class="arrow"><a href="/blog/category/{{ category.slug }}?page={{ pag }}{{ post.previous_page_number }}">«</a></li>
{% else %}
<li class="disabled"><a href="">«</a></li>
{% endif %}
{% for pag in post.paginator.page_range %}
{% if pag == post.number %}
<li class="active"><a href="/blog/category/{{ category.slug }}?page={{ pag }}">{{ pag }}</a></li>
{% else %}
<li><a href="/blog/category/{{ category.slug }}?page={{ pag }}">{{ pag }}</a></li>
{% endif %}
{% endfor %}
{% if post.has_next %}
<li class="arrow"><a href="/blog/category/{{ category.slug }}?page={{ pag }}{{ post.next_page_number }}">»</a></li>
{% else %}
<li class="disabled"><a href="">»</a></li>
{% endif %}
</ul>
</div>
</div>
И можем наслаждаться результатом наших трудов, как показано на видео.
Делал согласно документации Django и исползовал запрос в поиске django pagination
Ваши комментарии
Комментарии могут оставлять только зарегистрированые пользователи!