使用基于类的视图具有类别 slug 和 Post slug 的 URL

Posted

技术标签:

【中文标题】使用基于类的视图具有类别 slug 和 Post slug 的 URL【英文标题】:Urls with Categories slug and Post slug using Class Based View 【发布时间】:2019-04-19 11:57:15 【问题描述】:

我正在开发一个简单的博客来学习 Django。我希望每个帖子都有这样的路径:

/category-1/title-post /category-2/title-post 等等..

urls.py

下面
from django.urls import include, path
from .views import CategoryList, PostList, SingleCategory, SinglePost, SingleTag, TagList

urlpatterns = [
        path("", PostList.as_view(), name="list_post"),
        path("<slug:slug>", SinglePost.as_view(), name="single_post"),
        path("tags/", TagList.as_view(), name="list_tag"),
        path("tags/<slug:slug>", SingleTag.as_view(), name="single_tag"),
        path("categories/", CategoryList.as_view(), name="list_category"),
        path("categories/<slug:slug>", SingleCategory.as_view(), name="single_category"),
]

还有 views.py

from django.shortcuts import render
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView

from .models import Category, Post, Tag
# Create your views here.

class CategoryList(ListView):
    model = Category
    context_object_name = 'category_list'
    template_name = "list_category.html"


class SingleCategory(DetailView):
    model = Category
    template_name = "single_category.html"


class PostList(ListView):
    model = Post
    queryset = Post.objects.order_by('-id')
    context_object_name = 'post_list'
    template_name = "list_post.html"
    paginate_by = 4


class SinglePost(DetailView):
    model = Post
    template_name = "single_post.html"


class TagList(ListView):
    model = Tag
    context_object_name = 'tag_list'
    template_name = "list_tag.html"


class SingleTag(DetailView):
    model = Tag
    template_name = "single_tag.html"

这里models.py

class Category(models.Model):
    category_name = models.CharField(
                max_length=50,
                )
    slug = models.SlugField(
                unique=True,
                )

    def __str__(self):
        return self.category_name

    def get_absolute_url(self):
        return reverse("single_category", kwargs="slug": self.slug)


class Post(models.Model):
    title = models.CharField(
                max_length=50,
                )
    slug = models.SlugField(
                unique=True,
                )
    content = models.TextField()
    tag = models.ManyToManyField(
                Tag,
                related_name="tag_set",
                )
    category = models.ForeignKey(
                    Category,
                    on_delete=models.CASCADE,
                    related_name="category_set",
                    )
    highlighted = models.BooleanField(
                    default=False,
                    )

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("single_post", kwargs="slug": self.slug)

    class Meta:
        ordering = ['-id']

我不明白如何更改“category-slug/” 中的路径“categories/”。我想为 categories / 做同样的事情,这必须在 category-slug/post-slug 中进行更改。

如何使用基于类的视图来做到这一点?

【问题讨论】:

【参考方案1】:

您可以在 URL 中定义任意数量的参数。然后,您需要覆盖 get_object 以按 slug 和类别获取相关帖子。

path('<slug:category_slug>/<slug:post_slug>', SinglePostByCategory.as_view(), 'single_post_by_category')

...

class SinglePostByCategory(DetailView):
    def get_queryset(self):
        return get_object_or_404(Post,
            category__slug=self.kwargs['category_slug'],
            slug=self.kwargs['post_slug']
        )

【讨论】:

我已经编辑了我的帖子以添加 models.py。如果我使用您的解决方案,则会显示此错误:django.urls.exceptions.NoReverseMatch: Reverse for 'single_post' with keyword arguments ''slug': 'articolo-due'' not found. 1 pattern(s) tried: ['(?P&lt;category_slug&gt;[-a-zA-Z0-9_]+)\\/(?P&lt;slug&gt;[-a-zA-Z0-9_]+)$'] 但我认为问题是由于我对 Django 的不强技能造成的错误。您可以使用 models.py 中的信息查看您过去的帖子吗? 这似乎与我的回答完全无关。您是否更改了“single_post”网址而不是添加单独的“single_post_by_category”? 你是对的!我已经纠正了我的错误,并且我使用了您的路径,只是视图名称有所不同。现在在 127.0.0.1:8000 我有这个错误:django.urls.exceptions.NoReverseMatch: Reverse for 'single_post' not found. 'single_post' is not a valid view function or pattern name.。如果我使用这个路径 127.0.0.1:8000/argomento-1/articolo-uno (我确定这是正确的),我有这个错误:AttributeError: Generic detail view SinglePost must be called with either an object pk or a slug in the URLconf. @DanielRoseman 我们不应该重写 get_object 方法而不是 get_queryset 吗?我已经像这样覆盖了 get_object 方法: class SinglePostByCategory(DetailView): def get_object(self, queryset=None): return get_object_or_404(Post, category__slug=self.kwargs['category_slug'], slug=self.kwargs['post_slug'] ) - 让它运行良好 - 我认为你需要更正答案......

以上是关于使用基于类的视图具有类别 slug 和 Post slug 的 URL的主要内容,如果未能解决你的问题,请参考以下文章

在永久链接中使用类别名称而不是类别 slug

Django Urls - 具有相同正则表达式的两个视图

基于 Django 类的“method_splitter” - 分别传递 2 个 slug 作为模型名称和字段值

在 RegEx 中的最后一个斜杠之后获取值并忽略类别 slug

在 url 中组合多个 slug

为啥我不能使用类别详细视图?如果在django中使用它得到404?