Model URLs
<li><a href="{% url "book-detail" book.id %}">{{ book.title }} (Rating: {{ book.rating }})</a> </li>
index.html
urlpatterns = [
path("", views.index),
path("<int:id>", views.book_detail, name="book-detail")
]
urls.py
- URL을 생성하기 위해 {% url %} 템플릿 태그 사용
def get_absolute_url(self):
return reverse("book-detail", args=[self.id])
models.py
<li><a href="{{ book.get_absolute_url }}">{{ book.title }} (Rating: {{ book.rating }})</a> </li>
index.html
- 모델에서 정의한 get_absolute_url()을 그대로 호출해 링크를 생성
- 가독성 향상 + DRY 원칙(중복 피하기)
간단한 경우: {% url %} 사용
반복적으로 URL을 생성하거나 많은 템플릿에서 사용되는 경우: get_absolute_url() 정의해서 사용하면 유지보수에 훨씬 좋음!
models.py
Slugfield
slug = models.SlugField(default="", null=False) # harry-potter-1
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
# models.py
- .save() 호출 시 자동으로 slug 생성 (또는 갱신)
- slugify("Harry Potter 1") → "harry-potter-1"처럼 영어 소문자와 하이픈 형태로 변환
python manage.py makemigrations
Migrations for 'book_outlet':
book_outlet/migrations/0003_book_slug.py
+ Add field slug to book
slugfield란?
- models.py에서 다음을 수정하거나 추가했을 때:
- 필드 추가/수정/삭제
- 모델 추가/삭제
- 필드 옵션 변경 (예: blank=True, null=False, default='x' 등)
python manage.py migrate
- makemigrations를 한 후, 변경 내용을 DB에 적용하고 싶을 때
python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, book_outlet, contenttypes, sessions
Running migrations:
Applying book_outlet.0003_book_slug... OK
❯ python manage.py shell
7 objects imported automatically (use -v 2 for details).
Python 3.13.5 experimental free-threading build (main, Jul 15 2025, 14:26:58) [Clang 15.0.0 (clang-1500.3.9.4)]
Type 'copyright', 'credits' or 'license' for more information
IPython 9.4.0 -- An enhanced Interactive Python. Type '?' for help.
Tip: IPython 9.0+ has hooks to integrate AI/LLM completions.
In [1]: from book_outlet.models import Book
In [2]: Book.objects.get(title="Harry Potter 1").save()
In [3]: Book.objects.get(title="Harry Potter 1").slug
Out[3]: 'harry-potter-1'
In [4]: Book.objects.get(title="Lord of the Rings").save()
In [5]: Book.objects.get(title="Lord of the Rings").slug
Out[5]: 'lord-of-the-rings'
In [6]: Book.objects.get(title="My Story").save()
In [7]: Book.objects.get(title="My Story").slug
Out[7]: 'my-story'
In [8]:
In [8]: Book.objects.get(title="Some random book").save()
In [9]: Book.objects.get(title="Some random book").slug
Out[9]: 'some-random-book'
from django.shortcuts import get_object_or_404, render
from django.http import Http404
from .models import Book
# Create your views here.
def index(request):
books = Book.objects.all()
return render(request, "book_outlet/index.html", {
"books": books
})
def book_detail(request, slug):
# try:
# book = Book.objects.get(pk=id)
# except:
# raise Http404()
book = get_object_or_404(Book, slug=slug) # 위와 같은 방법.. 404 page 생성
return render(request, "book_outlet/book_detail.html", {
"title": book.title,
"author": book.author,
"rating": book.rating,
"is_bestseller": book.is_bestselling
})
views.py
def get_absolute_url(self):
return reverse("book-detail", args=[self.slug])
models.py
- reverse("book-detail", args=[self.slug]): urls.py에서 name이 "book-detail"인 URL 패턴을 찾아서, args에 들어있는 값을 URL의 변수 자리에 넣어줍니다.
# book_outlet/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index),
path("<slug:slug>/", views.book_detail, name="book-detail"), # 수정됨
]
오류
urls.py는 <int:id>가 아니라 <slug:slug>로 받아야 self.slug와 매칭됨. 현재는 args=[self.slug]인데 URL 패턴에서는 id만 찾고 있어서 NoReverseMatch가 발생한 것. 수정 후 서버 재시작하거나 저장만 해도 반영됩니다.
slug = models.SlugField(default="", null=False, db_index=True, primary_key=True) # Harry Potter 1 => harry-potter-1
models.py
- db_index = True, primary_key=True
Aggregation & Ordering
def index(request):
books = Book.objects.all()
num_books = books.count()
avg_rating = books.aggregate(Avg("rating"))
return render(request, "book_outlet/index.html", {
"books": books,
"total_number_of_books": num_books,
"average_rating": avg_rating
})
views.py
<hr>
<p>Total Number of Books: {{ total_number_of_books }}</p>
<p>Average Rating: {{ average_rating }}</p>
</hr>
index.html
<p>Average Rating: {{ average_rating.rating__avg }}</p>
index.html
books = Book.objects.all().order_by("-title")
views.py
- title말고 rating 등 다른 것도 가능
'Programming > Django' 카테고리의 다른 글
| [Python Django] 💥 Django Admin prepopulated_fields 오류 해결기: slug 컬럼 없음 에러 (3) | 2025.07.23 |
|---|---|
| [Python Django] The Practical Guide - Admin, Relationship (3) | 2025.07.23 |
| [Python Django] The Practical Guide - Data & Models (2) (2) | 2025.07.22 |
| [Python Django] The Practical Guide - Data & Models (4) | 2025.07.22 |
| [Python Django - The Practical Guide] 장고로 블로그 만들기 프로젝트 (기초) (7) | 2025.07.21 |