You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django实现同分类下文章上一篇/下一篇切换功能求助

实现同分类文章上下篇切换方案

1. 完善模型(添加排序字段与上下篇查询方法)

首先给Post模型添加排序字段(比如创建时间),并新增获取上下篇的方法,同时修正get_absolute_url(URL需包含分类slug):

from django.db import models
from django.urls import reverse

class Home(models.Model):
    slug = models.SlugField(max_length=266, unique=True, db_index=True, verbose_name=('URL'))
    title = models.CharField(max_length=250)
    top_description = models.TextField(max_length=700, blank=False)

    class Meta:
        verbose_name = 'Главная'
        verbose_name_plural = 'Главная'

    def __str__(self):
        return self.title

class Category(models.Model):
    slug = models.SlugField(max_length=266, unique=True, db_index=True, verbose_name=('URL'))
    description = models.TextField(max_length=700, 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, blank=False)
    cat = models.ForeignKey('Category', on_delete=models.PROTECT, null=True)
    # 新增排序字段:创建时自动填充,用于确定文章顺序
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

    class Meta:
        # 默认按创建时间倒序排列,最新文章在前
        ordering = ['-created_at']

    def __str__(self):
        return self.slug

    def get_absolute_url(self):
        # 修正URL生成逻辑,包含分类slug以匹配路由规则
        return reverse('post', kwargs={'category_slug': self.cat.slug, 'post_slug': self.slug})

    def get_previous_post(self):
        # 获取同分类下,创建时间早于当前的最后一篇(上一篇)
        return Post.objects.filter(cat=self.cat, created_at__lt=self.created_at).order_by('-created_at').first()

    def get_next_post(self):
        # 获取同分类下,创建时间晚于当前的第一篇(下一篇)
        return Post.objects.filter(cat=self.cat, created_at__gt=self.created_at).order_by('created_at').first()

2. 修正视图逻辑

修改content_post视图,获取当前文章对象并查询上下篇:

from django.shortcuts import render, get_object_or_404
from .models import Post, Category

def content_category(request, category_slug):
    category_obj = get_object_or_404(Category, slug=category_slug)
    # 获取分类下所有文章,按创建时间倒序展示
    posts = Post.objects.filter(cat=category_obj).order_by('-created_at')
    return render(request, 'content/season.html',{
        'category': category_obj,
        'posts': posts
    })

def content_post(request, category_slug, post_slug):
    # 获取当前文章,同时验证所属分类是否匹配
    post_obj = get_object_or_404(Post, slug=post_slug, cat__slug=category_slug)
    # 调用模型方法获取上下篇
    prev_post = post_obj.get_previous_post()
    next_post = post_obj.get_next_post()
    return render(request, 'content/post.html', {
        'post': post_obj,
        'prev_post': prev_post,
        'next_post': next_post
    })

3. 完善URL配置

给视图添加name属性,确保反向解析URL正常工作:

from django.urls import path
from . import views

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

4. 修改模板渲染上下篇链接

在文章详情模板post.html中,根据上下篇是否存在渲染有效链接:

<div class="bootons-navigation">
    {% if prev_post %}
    <span class="span__bootons-navigatiom">
        <a href="{{ prev_post.get_absolute_url }}" title="previous">previous</a>
    </span>
    {% endif %}
    {% if next_post %}
    <span class="span__bootons-navigatiom">
        <a href="{{ next_post.get_absolute_url }}" title="next">next</a>
    </span>
    {% endif %}
</div>

关键说明

  • 排序自定义:如果不想用创建时间排序,可添加自定义排序字段(如order = models.IntegerField(default=0)),然后将查询条件中的created_at替换为order即可。
  • 模型规范:类名采用大驼峰命名(如Post而非post),符合Django开发规范,避免潜在问题。
  • URL一致性:必须确保get_absolute_url生成的URL与路由配置结构完全匹配,否则会出现跳转错误。

内容的提问来源于stack exchange,提问作者Yurko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:12:05