Django Slug + ID URL:复制 Dev.to 的 URL 模式
我们版本的网址
展望未来
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
我喜欢dev.to 的一点是它的 URL 设计。它将 slug 与代表某种内部索引值的哈希值结合起来,以确保唯一性。你可以在我的文章“自动生成 Makefile 文档”中看到一个例子,该文章的 URL 为“ https://dev.to/feldroy/autodocumenting-makefiles-175b ”。
让我们来分析一下这个网址:
feldroy是我的公司名称。autodocumenting-makefiles这是个小白鼠,它是根据文章标题生成的。175b是一个哈希值,要么存储在索引字符字段中,要么由路由器分解为数字主键。
以下是看待他们网址设计的另一种方式:
/<org-or-username>/<slugified-title>/<hashed-id>
让我们看看如何使用 Django 来实现这种技术的简化版本。
我们版本的网址
我们将采用Dev.to实现的简化版本。我们的实现将使用数据库主键来确保唯一性,而不是Dev.to所依赖的哈希值。
/<username>/<slugified-title>/<primary-key>/
好了,既然我们已经确定了网址设计,那就开始构建吧!
模型
存储数据!
# articles/models.py
from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _
class Article(models.Model):
title = models.CharField(_("Title"), max_length=100)
slug = models.CharField(_("Slug"), max_length=100)
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
# More fields...
表格
收集并验证数据!
# articles/forms.py
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('title', ) # more fields
观点
现在我们有了模型和表单,接下来让我们构建视图:
# articles/views.py
from django.shortcuts import get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils import slugify
from django.views.generic import CreateView, DetailView, UpdateView
from .forms import ArticleForm
from .models import Article
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
form_class = ArticleForm
def form_valid(self, form):
# Save the data to an article object -
# this hasn't yet saved to the database.
article = form.save(commit=False)
article.slug = slugify(article.title)
article.author = self.request.user
# Save again - this time to the database
article.save()
return super().form_valid(form)
class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model = Article
form_class = ArticleForm
def get_object(self):
# We get records by primary key, which ensures that
# changes in the title or slug doesn't break links
return get_object_or_404(Article,
id=self.kwargs['pk'],
author__username=self.kwargs['username'],
author=self.request.user
)
def form_valid(self, form):
# Update the slug if the title has changed.
article = form.save(commit=False)
article.slug = slugify(article.title)
article.save()
return super().form_valid(form)
class ArticleDetailView(DetailView):
model = Article
def get_object(self):
# We get records by primary key, which ensures that
# changes in the title or slug doesn't break links
return get_object_or_404(Article,
id=self.kwargs['pk'],
author__username=self.kwargs['username']
)
网址
让我们把这个路由到我们的URL中:
# articles/urls.py
from django.urls import path
from articles import views
urlpatterns = [
path(route='/new/',
view=views.ArticleCreateView.as_view(),
name='create',
),
path(route='/<slug:username>/<slug:slug>/<int:pk>/edit/',
view=views.ArticleUpdateView.as_view(),
name='update',
),
path(route='/<slug:username>/<slug:slug>/<int:pk>/',
view=views.ArticleDetailView.as_view(),
name='detail',
),
]
在项目根配置文件中,我们添加以下内容:
# config/urls.py or wherever you stick the project's root urls.py
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
# Django Admin, change this URL
path('two-scoops-of-django-is-awesome', admin.site.urls),
# Articles management
path('', include('articles.urls', namespace='article')),
# More URLS here
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# There's certainly more URLs down here
添加模板,瞧,一个遵循Dev.to URL 设计的 Django 示例就完成了!
展望未来
经验丰富的 Django 用户都知道,方法中的 slugification 逻辑form_valid应该放在 Article 模型的方法中,而不是视图中。这正是我们在《Django 入门指南》save()中讨论的内容。
说到这里,如果你想学习各种高级技巧和窍门,可以看看我和我妻子合著的以冰淇淋为主题的Django 最佳实践书籍和课程。
文章来源:https://dev.to/danielfeldroy/django-slug-id-url-design-3l8b
