Python 基于模型中的值创建URL

Python 基于模型中的值创建URL,python,django,Python,Django,我想创建一个博客页面,它可以完美地工作,但我想更改特定博客文章的URL。目前,特定博客文章的URL是myurl.com/blog/pk,但我希望改为myurl.com/blog/category/title。我该怎么做?如果您喜欢,也请欣赏对代码的任何批评 型号.py from django.db import models class Category(models.Model): name = models.CharField(max_length=20) class Post(

我想创建一个博客页面,它可以完美地工作,但我想更改特定博客文章的URL。目前,特定博客文章的URL是myurl.com/blog/pk,但我希望改为myurl.com/blog/category/title。我该怎么做?如果您喜欢,也请欣赏对代码的任何批评

型号.py

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=20)

class Post(models.Model):
    title = models.SlugField(max_length = 250, null = True, blank = True)
    body = models.TextField()
    created_on = models.DateTimeField(null=True)
    last_modified = models.DateTimeField(null=True)
    categories = models.ManyToManyField('Category', related_name='posts')

class Comment(models.Model):
    author = models.CharField(max_length=60)
    body = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    post = models.ForeignKey('Post', on_delete=models.CASCADE)
视图.py

from django.shortcuts import render
from .models import Post
from .models import Comment
from .forms import CommentForm
from django.http import HttpResponse


def blog_index(request):
    posts = Post.objects.all().order_by('-created_on')
    context = {
        "posts": posts,
    }
    return render(request, "blog_index.html", context)


def blog_category(request, category):
    posts = Post.objects.filter(
        categories__name__contains=category
    ).order_by(
        '-created_on'
    )
    if not posts:
        return HttpResponse(status=404)

    context = {
        "category": category,
        "posts": posts
    }
    return render(request, "blog_category.html", context)


def blog_detail(request, pk):
    post = Post.objects.get(pk=pk)

    form = CommentForm()
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = Comment(
                author=form.cleaned_data["author"],
                body=form.cleaned_data["body"],
                post=post
            )
            comment.save()

    comments = Comment.objects.filter(post=post)
    context = {
        "post": post,
        "comments": comments,
        "form": form,
    }
    return render(request, "blog_detail.html", context)
from django.urls import path
from . import views

urlpatterns = [
    path("", views.blog_index, name="blog_index"),
    path("<int:pk>/", views.blog_detail, name="blog_detail"),
    path("<category>/", views.blog_category, name="blog_category"),
]
应用程序URL.py

from django.shortcuts import render
from .models import Post
from .models import Comment
from .forms import CommentForm
from django.http import HttpResponse


def blog_index(request):
    posts = Post.objects.all().order_by('-created_on')
    context = {
        "posts": posts,
    }
    return render(request, "blog_index.html", context)


def blog_category(request, category):
    posts = Post.objects.filter(
        categories__name__contains=category
    ).order_by(
        '-created_on'
    )
    if not posts:
        return HttpResponse(status=404)

    context = {
        "category": category,
        "posts": posts
    }
    return render(request, "blog_category.html", context)


def blog_detail(request, pk):
    post = Post.objects.get(pk=pk)

    form = CommentForm()
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = Comment(
                author=form.cleaned_data["author"],
                body=form.cleaned_data["body"],
                post=post
            )
            comment.save()

    comments = Comment.objects.filter(post=post)
    context = {
        "post": post,
        "comments": comments,
        "form": form,
    }
    return render(request, "blog_detail.html", context)
from django.urls import path
from . import views

urlpatterns = [
    path("", views.blog_index, name="blog_index"),
    path("<int:pk>/", views.blog_detail, name="blog_detail"),
    path("<category>/", views.blog_category, name="blog_category"),
]

我确信你不想使用标题。标题通常可以包含空格(
)、标点(
~!?
等)和特殊字符。URL不能包含这些字符中的大多数。确实可以避开这些字符,但URL看起来非常难看,如:

myurl.com/some%20title%20containing%20spaces
现在这不是很容易理解

但是,您可以使用一个slug和一个slug。一个
SlugField
是一个
CharField
,但是它会进行一些清理以避免丑陋的URL。例如,
“包含空格的某些标题”
将转换为
包含空格的某些标题

您可以将
SlugField
添加到
CategoryModel
中,如:

from django.utils.text import slugify

class Category(models.Model):
    name = models.CharField(max_length=20)
    slug = models.SlugField(unique=True, blank=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super().save(*args, **kwargs)
然后,我们可以从我们的角度对slug进行过滤:

from django.shortcuts import get_list_or_404
from .models import Post

def blog_category(request, category_slug):
    posts = get_list_or_404(Post.objects.filter(
        categories__slug=category_slug
    ).order_by(
        '-created_on'
    ))

    context = {
        'category': category,
        'posts': posts
    }
    return render(request, 'blog_category.html', context)

我确信你不想使用标题。标题通常可以包含空格(
)、标点(
~!?
等)和特殊字符。URL不能包含这些字符中的大多数。确实可以避开这些字符,但URL看起来非常难看,如:

myurl.com/some%20title%20containing%20spaces
现在这不是很容易理解

但是,您可以使用一个slug和一个slug。一个
SlugField
是一个
CharField
,但是它会进行一些清理以避免丑陋的URL。例如,
“包含空格的某些标题”
将转换为
包含空格的某些标题

您可以将
SlugField
添加到
CategoryModel
中,如:

from django.utils.text import slugify

class Category(models.Model):
    name = models.CharField(max_length=20)
    slug = models.SlugField(unique=True, blank=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super().save(*args, **kwargs)
然后,我们可以从我们的角度对slug进行过滤:

from django.shortcuts import get_list_or_404
from .models import Post

def blog_category(request, category_slug):
    posts = get_list_or_404(Post.objects.filter(
        categories__slug=category_slug
    ).order_by(
        '-created_on'
    ))

    context = {
        'category': category,
        'posts': posts
    }
    return render(request, 'blog_category.html', context)

您不能使用标题,或者至少不建议使用,因为标题可以包含空格、标点符号等。通常使用slug。这很有意义。将我的模型字段从
Charfield
更改为
slug
,是否会导致任何问题@WillemVanonSem通常您会为此添加一个
slug
字段。您不能使用标题,或者至少不建议这样做,因为标题可以包含空格、标点符号等。通常情况下会使用slug。这很有意义。将我的模型字段从
Charfield
更改为
slug
,是否会导致任何问题@WilleMVanonSem通常您会为此添加一个
slug
字段。运行
migrate
会出现以下错误-
django.db.utils.IntegrityError:UNIQUE constraint failed:new\uu blog\u category。slug
也不是
blog\u detail()
?目前,
blog\u category()
创建了一个页面,其中包含我想要的该类别下的所有帖子。我只想将单击的博客文章的最终url命名为
MyUrl.com/blog/category/title
@LesnieSncheider:迁移失败的原因是您添加了一个额外的字段
slug
,而现在该字段在所有记录中都不是唯一的。如果你想在
博客
上找到slug,你确实应该将它添加到
博客
模型中。我从
类别
模型中删除了
slug
,现在它仍然会引起同样的问题。@Lesniesdheider:是的,那是因为它仍然在迁移文件中,你也应该删除它。运行
migrate
会给我以下错误-
django.db.utils.integrityyror:UNIQUE约束失败:新建博客类别。slug
也不是
blog\u detail()
决定特定博客文章的URL而不是
blog\u类别()
?目前,
blog\u category()
创建了一个页面,其中包含我想要的该类别下的所有帖子。我只想将单击的博客文章的最终url命名为
MyUrl.com/blog/category/title
@LesnieSncheider:迁移失败的原因是您添加了一个额外的字段
slug
,而现在该字段在所有记录中都不是唯一的。如果你想在
博客
上找到slug,你确实应该将它添加到
博客
模型中。我从
类别
模型中删除了
slug
,现在它仍然会导致同样的问题。@Lesniesdheider:是的,这是因为它仍然在迁移文件中,你也应该删除它。