[day-35] 데이터 업로드, 불러오기, 검색

Joohyung Park·2024년 2월 25일
0

[모두연] 오름캠프

목록 보기
66/95

URL 기획

1. 다음 url이 실제 작동하도록 해주세요.
1.1 'blog/'
1.2 'blog/<int:pk>'

###################################
앱이름: blog    views 함수이름   html 파일이름  비고
'blog/'         blog            blog.html	
'blog/<int:pk>' post            post.html

pillow 라이브러리

많은 프레임워크와 라이브러리가 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, media 폴더

  • 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 객체의 제목과 내용을 리스트 항목으로 표시한다. 여기서 dbview 함수에서 render 함수를 호출할 때 전달한 context 데이터이다.

이후, 각 객체에 해당하는 링크를 생성하며 인자로 blog_detail.id를 전달한다.

해당 링크를 클릭하면 해당 Post 객체의 상세 페이지로 이동한다.

views.py

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)
  • modelPost 객체를 불러옴
  • 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 템플릿으로 렌더링
profile
익숙해지기 위해 기록합니다

0개의 댓글