1. 다음 url이 실제 작동하도록 해주세요.
1.1 'blog/'
1.2 'blog/<int:pk>'
###################################
앱이름: blog views 함수이름 html 파일이름 비고
'blog/' blog blog.html
'blog/<int:pk>' post post.html
많은 프레임워크와 라이브러리가 pillow
라는 이미지 관련 라이브러리를 사용한다.
이미지를 자르거나, 확대하거나, 축소하거나, 저장하거나 등이 사용된다.
pip install pillow
# blog > models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
contents = models.TextField()
# main_image = models.ImageField(upload_to='blog/', blank=True, null=True) # upload_to='blog/' : blog 폴더 안에 저장
main_image = models.ImageField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
ImageField
라는 필드를 주어 이미지를 저장하도록 하였다.
blank=True
: 필드를 비워 놓아도 된다. 기본값은 False
null=True
: 필드가 DB에 저장될 때 Null값을 가질 수 있다. 기본값은 False
static
: 프로젝트의 정적 파일들이 서비스될 URL을 설정하며, 웹 브라우저에서 정적 파일을 불러올 때 이 URL을 기준으로 불러온다.
media
: 사용자가 업로드한 미디어 파일들이 서비스될 URL을 설정하며, 웹 브라우저에서 미디어 파일을 불러올 때 이 URL을 기준으로 불러온다.
STATIC_URL = "static/"
STATICFILES_DIRS = [BASE_DIR / "static"]
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
# blog_detail.html
<h1>게시판</h1>
<p>{{db.title}}</p>
<p>{{db.contents}}</p>
<p>{{db.updated_at}}</p>
{% if db.main_image %}
<!-- db.main_image.url: /media/a.jpg -->
<!-- db.main_image.url: /media/blog/2310/11/a.jpg와 같이 저장합니다. -->
<img src="{{ db.main_image.url }}" alt="">
{% endif %}
<a href="{% url 'blog_list' %}">뒤로가기</a>
<p>{{db.main_image}}</p>
<!-- db.main_image: a.jpg -->
Post
객체에 main_image
속성이 있는 경우(이미지가 업로드 되어있는 경우) <img>
태그를 사용하여 이미지를 표시한다.
blog_list
라는 이름의 URL 패턴으로 '뒤로가기' 링크를 생성하며 템플릿 문법으로 이미지 파일의 이름을 그대로 출력한다.
# blog_list
<h1>게시판</h1>
<form action="" method="get">
<input name="q" type="search">
<button type="submit">검색</button>
</form>
<ul>
{% for blog_detail in db %}
<li>
<a href="{% url 'blog_detail' blog_detail.id %}">{{ blog_detail.title }}</a>
<p>{{blog_detail.contents}}</p>
</li>
{% endfor %}
</ul>
검색 form
을 구현한 예시이다.
사용자가 검색어를 입력하고 검색
버튼을 클릭하면, 현재 URL에 ?q=검색어
형식의 쿼리 문자열이 추가되어 GET 요청이 발생한다.
db
변수에 담긴 Post
객체들을 순회하며 각 Post
객체의 제목과 내용을 리스트 항목으로 표시한다. 여기서 db
는 view
함수에서 render
함수를 호출할 때 전달한 context
데이터이다.
이후, 각 객체에 해당하는 링크를 생성하며 인자로 blog_detail.id
를 전달한다.
해당 링크를 클릭하면 해당 Post
객체의 상세 페이지로 이동한다.
blog
앱의 views.py
는 다음과 같다.
from django.shortcuts import render
from .models import Post
from django.db.models import Q
def blog_list(request):
if request.GET.get("q"):
q = request.GET.get("q")
db = Post.objects.filter(
Q(title__icontains=q) | Q(contents__icontains=q)
).distinct()
else:
db = Post.objects.all()
context = {
"db": db,
}
return render(request, "blog/blog_list.html", context)
def blog_detail(request, pk):
db = Post.objects.get(pk=pk)
context = {
"db": db,
}
return render(request, "blog/blog_detail.html", context)
model
의 Post
객체를 불러옴from django.db.models import Q
: ORM에서 복잡한 데이터 쿼리를 생성할 수 있게 해주는 Q 객체를 임포트# or연산
Q(title__icontains=q) | Q(contents__icontains=q)
blog_list
함수 : GET
요청의 쿼리 문자열에서 q
키의 값을 가져와, 이 값을 사용하여 Post
객체들을 DB에서 검색한다. request.GET
: 쿼리 문자열을 파싱한 결과를 담고 있는 딕셔너리Q(title__icontains=q) | Q(contents__icontains=q)
: title 필드에 'q' 값이 포함되어 있거나(icontains), contents 필드에 'q' 값이 포함되어 있는(icontains) Post 객체들을 찾는 쿼리를 생성__icontains
: 대소문자를 구분하지 않는 부분 문자열 검색을 수행하는 필드 조회 키워드.distinct()
: 중복된 결과 제거blog_detail(request, pk)
: pk
에 해당하는 Post
객체를 데이터베이스에서 가져와, 이를 blog_detail.html
템플릿으로 렌더링