본 글은 Holix의 "리액트와 함께 장고 시작하기 Complete" 강의를 듣고 작성한 일지입니다.
이번엔 장고의 QuerySet 을 이용하여 간단한 검색 서비스를 구현해보겠습니다. 이를 위해서 이전에 다루지 않았던 views.py 파일에 코드를 추가해야 합니다.
# views.py
from django.shortcuts import render
from .models import Post
# Create your views here.
def post_list(request):
qs = Post.objects.all()
q = request.GET.get('q', '') # q가 없으면 빈 문자열 리턴
if q:
qs = qs.filter(content__icontains=q)
# blog1/templates/blog1/post_list.html
return render(request, 'blog1/post_list.html', {
'post_list': qs,
'q': q,
})
request.GET.get('q'): 우리가 흔히 url에서 볼 수 있는 "?q=" 형식에서의 q를 말합니다. = 뒤에 특정 단어가 있으면 그것을 q라는 변수에 저장하고 없으면 빈 문자열을 저장하겠다는 의미입니다.
render: 직접 만든 html 파일을 웹에 띄울 수 있도록(=렌더링) 지원하는 장고의 기능
아래는 간단하게 표현한 html 파일입니다. 장고에서는 저희가 직접 작성한 html 파일의 위치를 현재 앱 아래 templates 라는 폴더에 있다고 인식합니다. 따라서 templates 아래 폴더를 따로 두었다면(저처럼) 위에서 render() 를 작성할 때 나머지 디렉토리 위치를 적어주시면 됩니다.
<!-- post_list.html -->
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<title>Instagram / Post List</title>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
</head>
<body>
<form action="" method="get">
<input type="text" name="q" value="{{ q }}" /> <!-- name="q"로 지정해야 views.py에서 get 방식으로 q값을 가져온 것과 동일하게 동작 -->
<input type="submit" value="검색" /> <!-- value=""는 기본적으로 표시되는 항목 이름 -->
</form>
<table class="table table-bordered table-hover">
<tbody>
{% for post in post_list %}
<tr>
<td>
{% if post.photo %}
<img src="{{ post.photo.url }}" style="width: 100px;" />
{% else %}
No Photo
{% endif %}
</td>
<td>
{{ post.content }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
<link href ... >: Bootstrap에서 제공하는 탬플릿으로 홈페이지를 방문하면 더 자세한 내용이 나와있습니다.
아래처럼 "감을" 이라고 검색하면 content 속성 안에 해당 단어가 있는 데이터를 보여주고, form에는 value="{{ q }}" 라고 지정했기 때문에 텍스트 창에 그대로 값이 남아있게 됩니다.
장고는 부가 기능을 제공하는 extensions가 있습니다. 그중에서도 QuerySet 을 사용하면서 그 내부의 SQL 쿼리문이 어떤지 보여주는 기능이 있습니다.
pip install django-extensions
그리고 settings.py 파일에 가서 INSTALLED_APPS 에 해당 패키지를 추가해야 합니다.
INSTALLED_APPS = [
# django apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# third apps
'django_extensions',
# local apps
'blog1',
]
pip 다운로드할 때와 다르게 '-"가 아닌 "_" 임에 주의하세요.
python manage.py shell_plus --print-sql -ipython
아래처럼 장고의 기본 QuerySet 을 ipython 터미널에 입력하면 이것의 실행을 위한 SQL 쿼리문이 함께 나타납니다.
Post.objects.all()
QuerySet 에 대해서 정렬이나 범위에 조건을 가할 수도 있지만 파이썬 리스트와 비슷한 것 같으면서도 기본적으로 DB를 다루는 것이다 보니 완전히 동일하지 않습니다.
Post.objects.all().order_by('-id') # id 순으로 정렬(큰 순서대로)
Post.objects.all()[:1]
파이썬 리스트에서는 슬라이싱을 할 때 음수 표시를 할 수도 있고(맨 마지막 원소), [start:end:step] 순서로 step을 지정해주면 마지막에 몇 개씩 뛰어넘을 것인지도 정할 수 있습니다. 하지만 QuerySet 에서는 이러한 문법을 지원하지 않습니다!!
아예 models.py 파일에 Class Meta 를 활용하여 자동 정렬하도록 만들 수도 있습니다.
# models.py
from django.db import models
from .utils import uuid_name_upload_to
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
photo = models.ImageField(blank=True, upload_to=uuid_name_upload_to)
is_public = models.BooleanField(default=False, verbose_name='공개여부')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.content
# 정렬 조건 추가
class Meta:
ordering = ['-id']
'문돌이 존버 > Django 스터디' 카테고리의 다른 글
장고(Django) 관계(relationship)를 표현하는 모델 필드, ForeignKey (0) | 2021.08.07 |
---|---|
장고(Django) debug toolbar 설치 및 SQL 쿼리문 확인 (0) | 2021.08.07 |
장고(Django) 모델을 통한 조회(기초) (0) | 2021.08.07 |
장고(Django) media 파일 다루기 (0) | 2021.08.06 |
장고(Django) admin 페이지 커스터마이징 (0) | 2021.08.05 |