Джанго - функция перехода на предыдущий и следующий пост

Рейтинг: 0Ответов: 1Опубликовано: 25.02.2023

Всем доброго времени суток!

Проблема:

Есть категории со связанными постами. Нужно сделать, что бы на странице ПОСТ были 2 кнопки перехода на предыдущую и следующую страницу. Если предыдущей странице поста категории нет, то переход на главную, а если нет следующей странице поста, то на страницу следующей по порядку категории.

Я всю голову сломал, но даже логики этого выстроить не могу. Прошу помощи у знающих! Заранее спасибо за ответ!

    Models

class category(models.Model):
    slug = models.SlugField(max_length=266, unique=True, db_index=True, verbose_name=('URL'))
    description = models.TextField(max_length=700, verbose_name=('Описание'), blank=False)

    def __str__(self):
        return self.slug

    def get_absolute_url(self):
        return reverse('category', kwargs={'category_slug': self.slug})
    
class post(models.Model):
    slug = models.SlugField(max_length=266, unique=True, db_index=True, verbose_name=('URL'))
    description = models.TextField(max_length=700, verbose_name=('Описание'), blank=False)

    cat = models.ForeignKey('category', on_delete=models.PROTECT, null=True)

    def __str__(self):
        return self.slug

    def get_absolute_url(self):
        return reverse('post', kwargs={'post_slug': self.slug})


    Views
 
def ContentСategory(request, category_slug):
    category = get_list_or_404(post, slug=category_slug)
    category=category.objects.filter(slug=category_slug)
    return render(request, 'content/category.html',{'category':category})

def content_post(request, category_slug, post_slug):
    post = get_list_or_404(post, slug=post_slug)
    post = post.objects.filter(slug=post_slug, cat__slug=category_slug)
    return render(request, 'content/post.html', {'post': post}


    URLS

urlpatterns = [
    path('', views.ContentHome.as_view(), name='homepage'),
    path('<slug:category_slug>', views.ContentCategory, name='category'),
    path('<slug:category_slug>/<slug:post_slug>', views.ContentPost, name='post'),
]

Ответы

▲ 0

Тут непонятно как именно находить предыдущий и следующий, так как не ясна сортировка по которой они должны отображаться. Предположим, что нас интересует сортировка по slug. Тогда можно сделать как-то так

def get_next_post(post_slug, category_slug):  
    found = post.objects.first(cat__slug=category_slug, slug__gt=post_slug).order_by("slug")
    if not found:  # последний пост в данной категории, найдем первый в следующей
        found = post.objects.first(cat__slug_gt=category_slug).order_by("slug")
    return found


def get_previous_post(post_slug, category_slug):  
    found = post.objects.last(cat__slug=category_slug, slug__lt=post_slug).order_by("slug")

    # тут по задаче стоит, сразу ссылку домой, но я бы сделал навигацию одинаковой, 
    # предыдущий для первого поста в категории - это последний пост в предыдущей категории
    if not found:  
        found = post.objects.last(cat__slug_lt=category_slug).order_by("slug")
    return found


def content_post(request, category_slug, post_slug):
    found_post = get_object_or_404(post, slug=post_slug, cat__slug=category_slug)
    next = get_next_post(post_slug, category_slug)
    previous = get_previous_post(post_slug, category_slug)
    if next:
        next_url = next.get_absolute_url()
        next_title = "next"
    else:
        next_url = reverse("homepage")
        next_title = "home"

    if previous:
        previous_url = previous.get_absolute_url()
        previous_title = "previous"
    else:
        previous_url = reverse("homepage")
        previous_title = "home"


    return render(
        request, 
        "content/post.html", 
        {
            "post": found_post,
            "next_url": next_url,
            "next_title": next_title,
            "previous_url": previous_url,
            "previous_title": previous_title,
        },
    )