본래의 의미 - 신문 용어
신문이나 잡지에서는 어떤 방식으로 행하는가?
개발에서는 어떻게 활용이 되는가?
post/1
로 적혀있는 것보다는 post/what-is-slug
라고 써져 있는게 더 사람이 이해하기 편하다Django 를 이용하여 예시
# 글에 대한 meta 정보 를 이렇게 구성할 것이다.
<title> The 46 Year Old Virgin </title>
<content> A silly comedy movie </content>
<slug> the-46-year-old-virgin </slug>
실습 목표
실습 순서
주의사항
SlugField
로 필드를 정한다고 자동으로 그 필드가 slug로 채워지는 것이 아님pyenv 와 virtualenv 가 설치된 상태에서 테스트를 위한 가상환경을 구축한다.
pyenv install 3.8.10
pyenv virtualenv 3.8.10 slug-test
mkdir slug-test
cd slug-test
pyenv local slug-test
(slug-test)
표시가 보이면서 가상환경이 활성되어 있어야한다.python3 -m pip install django~=4.0.0
django-admin startproject django_project .
python3 manage.py migrate
python3 manage.py runserver
python manage.py startapp articles
# django_project/settings.py
INSTALLED_APPS = [
...
"articles", # new
]
from django.db import models
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("article_detail", args=[str(self.id)])
python manage.py makemigrations articles
python manage.py migrate
mkdir articles/templates
cat <<EOF> articles/templates/article_list.html
<h1>Articles</h1>
{% for article in object_list %}
<ul>
<li><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></li>
</ul>
{% endfor %}
EOF
cat <<EOF> articles/templates/article_detail.html
<div>
<h2>{{ object.title }}</h2>
<p>{{ object.body }}</p>
</div>
EOF
# articles/views.py
from django.views.generic import ListView, DetailView
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = "article_list.html"
class ArticleDetailView(DetailView):
model = Article
template_name = "article_detail.html"
from django.urls import path
from .views import ArticleListView, ArticleDetailView
urlpatterns = [
path("<int:pk>", ArticleDetailView.as_view(), name="article_detail"),
path("", ArticleListView.as_view(), name="article_list"),
]
# django_project/urls.py
from django.contrib import admin
from django.urls import path, include # new
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("articles.urls")), # new
]
python manage.py createsuperuser
# articles/admin.py
from django.contrib import admin
from .models import Article
class ArticleAdmin(admin.ModelAdmin):
list_display = ("title", "body",)
admin.site.register(Article, ArticleAdmin)
http://127.0.0.1:8000
로 들어가서 글 확인하기# articles/models.py
from django.db import models
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
slug = models.SlugField() # new
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("article_detail", kwargs={"slug": self.slug}) # new
python manage.py makemigrations articles
# 하지만, 이미 만들어져있는 django slug test 글에는 slug 필드가 존재하지 않아, 이것에 대하여 어떻게 처리할 것인지에 대한 에러가 발생되게됨
You are trying to add a non-nullable field 'slug' to article without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
# articles/models.py
from django.db import models
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
slug = models.SlugField(null=True) # new
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("article_detail", kwargs={"slug": self.slug})
python manage.py makemigrations articles
python manage.py migrate
django-slug-test
입력 후 저장# articles/urls.py
from django.urls import path
from .views import ArticleListView, ArticleDetailView
urlpatterns = [
path("<slug:slug>", ArticleDetailView.as_view(), name="article_detail"), # new
path("", ArticleListView.as_view(), name="article_list"),
]
# articles/models.py
from django.db import models
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
slug = models.SlugField(null=False, unique=True) # new
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("article_detail", kwargs={"slug": self.slug})
python manage.py makemigrations articles
python manage.py migrate
# articles/admin.py
from django.contrib import admin
from .models import Article
class ArticleAdmin(admin.ModelAdmin):
list_display = ("title", "body",)
prepopulated_fields = {"slug": ("title",)} # new
admin.site.register(Article, ArticleAdmin)
일반적인 상황에서는 admin에서 글을 작성하지 않고, 사용자가 글을 작성하게 될 것임.
그렇기 때문에 Django의 slugify 라는 내장도구를 이용해서 자동으로 필드가 채워지도록 재구성할 것임
Model의 save 메소드를 오버라이딩 하여 구현할 것임
from django.db import models
from django.template.defaultfilters import slugify # new
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
slug = models.SlugField(null=False, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("article_detail", kwargs={"slug": self.slug})
def save(self, *args, **kwargs): # new
if not self.slug:
self.slug = slugify(self.title)
return super().save(*args, **kwargs)
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField(max_length=1000)
slug = models.SlugField(max_length=40)
class Meta:
# index_together = [['id', 'slug']]
velog의 포스트 url은 slug를 이용하여 만들어져있다.
실제로 글을 작성해보고, 어떻게 작동하는지 확인해보았다.
글을 작성해보자
https://velog.io/@swhan9404/클린코드를-위한-Guard-Clause
-
로 바뀐다.똑같은 제목의 글을 작성해보자
https://velog.io/@swhan9404/클린코드를-위한-Guard-Clause-73bfzfea
-해쉬값
을 붙여서 해결한다.글 제목을 수정했을 때 글 링크는 변화가 없다
https://velog.io/@swhan9404/1234567891234567891.23-45
(1)2<3>4/5'6"7[8]9\1!2@3#4$5%6^7&8*9,1.2_3-4+5=
.
: 그대로유지-
: 그대로 유지