我想创建一个博客页面,它运行得很好,但我想更改特定博客文章的 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)
Views.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)
应用程序 urls.py
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"),
]
项目网址
path('blog/', include('blog.urls')),
最佳答案
我非常确信您不想想要使用标题。标题通常可以包含空格 ()、标点符号 (
~!#.?
等) 和特殊字符。 URL 不能包含大部分字符。人们确实可以转义这些字符,但 URL 看起来很难看,如下所示:
myurl.com/some%20title%20containing%20spaces
现在这不是很可读。
但是,您可以使用带有 SlugField
[Django-doc] 的 slug 。 SlugField
是一个 CharField
,但它会进行一些清理以避免丑陋的 URL。例如,'some title contains space'
将转换为 some-title-containing-spaces
。
您可以将 SlugField
添加到您的 CategoryModel
,如下所示:
from django.utils.text import <b>slugify</b>
class Category(models.Model):
name = models.CharField(max_length=20)
<b>slug = models.SlugField(unique=True, blank=True)</b>
def save(self, *args, **kwargs):
<b>self.slug = slugify(self.name)</b>
super().save(*args, **kwargs)
在urlpatterns
中,我们可以将slug
指定为:
# app/urls.py
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/<b><slug:category_slug></b>/', views.blog_category, name='blog_category'),
]
然后我们可以在 View 中过滤 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(
<b>categories__slug=category_slug</b>
).order_by(
'-created_on'
))
context = {
'category': category,
'posts': posts
}
return render(request, 'blog_category.html', context)
生成独特的slugs
有时可能会发生另一个Category
对象已经存在slug
的情况,我们可以使用脚本生成一个唯一的slug,例如:
from django.utils.text import slugify
from itertools import count
class Category(models.Model):
name = models.CharField(max_length=20)
<b>slug = models.SlugField(unique=True, blank=True)</b>
def save(self, *args, **kwargs):
for i in count():
slug = slugify('{}{}'.format(self.title, i or ''))
if not Category.objects.filter(slug=slug).exists():
break
self.slug = slug
super().save(*args, **kwargs)
关于python - 根据模型中的值创建 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56317508/