django - 从 int:pk 更改为 Slug
问题描述
在完成我的博客项目后,我找到了一种方法,从写博客的 id 到写一个函数来添加帖子标题成为一个 slug。
因此,我目前正在尝试将所有帖子详细信息切换为 slug,但是在完成所有操作后,我收到了一个页面错误 404,它并不能准确地表明我的代码有什么问题。
我的问题是,当我从将 url 从 int:id 更改为 slug 时,我还应该寻找什么来更改以避免页面错误 404?
在每个页面详细信息的 URL 中,我得到 int:id 不是帖子的标题和错误 404
我已经评论了添加 slug 功能:这是 models.py :
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
likes = models.ManyToManyField(
User, related_name='liked')
slug = models.SlugField(blank=True, null=True, max_length=120)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse("score:post-detail", kwargs={'slug': self.slug})
这是views.py
class PostDetailView(DetailView):
model = Post
template_name = "post_detail.html"
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data()
stuff = get_object_or_404(Post, id=self.kwargs['slug']) <- Error is coming here
total_likes = stuff.total_likes()
liked = False
if stuff.likes.filter(id=self.request.user.id).exists():
liked = True
context["total_likes"] = total_likes
context["liked"] = liked
return context
def LikeView(request):
post = get_object_or_404(Post, id=request.POST.get('id'))
liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
context = {
'total_likes': post.total_likes,
'liked': liked,
'post': post
}
if request.is_ajax:
html = render_to_string('like_section.html', context, request=request)
return JsonResponse({'form': html})
这是网址
urlpatterns = [
path('', PostListView.as_view(), name='score'),
path('<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
path('new/', PostCreateView.as_view(), name='post-create'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('<slug:slug>/update/', PostUpdateView.as_view(), name='post-update'),
path('<slug:slug>/delete/', PostDeleteView.as_view(), name='post-delete')
解决方案
首先,蛞蝓有问题。如果您发布两个标题相同的帖子会怎样?因为它们会以同样的方式被压制,你会失去出版物的独特性。我建议您在 stackoverflow 模型上作弊,该模型结合了 id 和 slugified 标题,就像您的浏览器中显示的那样。
其次,您的路径令人困惑最好使用诸如详细信息/“pk”或问题/“pk”/“slug”之类的值作为前缀
我认为错误来自网址,而这个:
stuff = get_object_or_404(Post, id=self.kwargs['slug'])
将其替换为:
stuff = get_object_or_404(Post, slug=self.kwargs['slug'])
或更好:
stuff = self.get_object()
最后,如果您在添加这样的网址后决定遵循我的建议,例如:
path('details/<int:pk>-<slug:sl>', views.PostDetailView.as_view())
您将不得不覆盖 DetailView 的 get_object() 方法
def get_object(self, queryset=None):
pk = self.kwargs.get('pk')
slug = self.kwargs.get('slug')
stuff = get_object_or_404(Post, id=pk,slug=slug)
return stuff
而不是像这样对url的常量部分进行后缀:
path('<slug:slug>/update/', PostUpdateView.as_view(), name='post-update'),
path('<slug:slug>/delete/', PostDeleteView.as_view(), name='post-delete')
这样做会帮助 django 区分你的 url
path('update/<slug:slug>', PostUpdateView.as_view(), name='post-
update'),
path('delete/<slug:slug>/', PostDeleteView.as_view(), name='post-
delete')
并且还要避免将 url 开头的参数作为:
path('<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
改为这样做
path('posts/<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
希望它会有所帮助:)
推荐阅读
- python - Django:将两个查询合二为一
- debugging - 如何在 VsCode 中调试 Flutter?
- c# - 在另一个存储过程中调用时抑制存储过程输出?
- javascript - Select2 按下 cmd 按钮时,多选框保持下拉打开
- postgresql - 有没有办法查看 pgAdmin 中的关系列?
- x509certificate - Can the same x509 certificate have two different PEM encoding?
- django - 使用 save() 复制模型实例的问题
- java - 在 @PostConstruct 不触发 ContextClosedEvent 时睡觉
- android - react-native run-android 失败并出现错误
- dailymotion-api - 在 Dailymotion API 上访问视频的“stream_h264_ld_url”字段