Photo 앱

사진들을 앨범으로 그룹화해 관리하고 각 사진에 대한 정보를 등록하고 열람할 수 있는 Photo 앱 개발

사진의 썸네일을 처리하기 위해 새로운 커스텀 필드가 필요하므로, Pillow 라이브러리를 활용해서 커스텀 필드를 작성해야 한다.

설계

테이블 설계

  1. Album 테이블

  2. Photo 테이블

하나의 앨범은 여러 개의 사진을 가질 수 있고, 하나의 사진은 하나의 앨범에만 속할 수 있으므로 다음 관계가 성립한다.

Album 테이블- 1 : N -Photo 테이블

URL 설계

포토앱 틀잡기

포토앱 생성

python manage.py startapp photo

INSTALLED_APPS 등록

    'photo.apps.PhotoConfig',

Model 코딩

models.py

admin.py

  1. 정의한 테이블이 Admin 사이트에 보이도록 admin.py 파일
  2. Admin 사이트의 모습을 정의하는 AlbumAdmin, PhotoAdmin 클래스 정의

외래 키로 연결된 Album, Photo 테이블 간에는 1:N 관계이므로 앨범 객체를 보여줄 때 객체에 연결된 사진 객체들을 같이 보여준다. 같이 보여주는 형식은 세로로 나열되는 형식인 Stackedlnline과 테이블 모양처럼 행으로 나열되는 형식인 Tabularlnline이 있다.

fields.py

사진을 저장하기 위한 필드인 ThumbnailImageField 커스텀 필드 작성

커스텀 필드를 작성할 때는 기존의 비슷한 필드를 상속받아 작성하는 것이 보통으로 이미지 관련 커스텀 필드는 ImageField 클래스를 상속받아 작성한다. ImageField 필드는 이미지 파일을 파일 시스템에 쓰고 삭제하는 작업이 필요하므로, ImageFieldFile 클래스가 필요하고 두 클래스를 연계시켜주는 코드도 필요하다.

DB에 반영

두 개의 테이블을 신규로 정의했으니까 DB에 반영해준다.

admin.py 파일에 정의된 StackedInline 설정에 따라, 입력 양식이 세로로 추가되는 방식으로 extra 설정에 따라 앨범 하나에 사진 2개를 입력할 수 있는 형식이다.

URLconf 코딩

BookMarkApp/urls.py

  1. /photo/ URL 요청이 오면, 포토 앱의 APP_URLCONF에 처리를 위임하도록
  2. 기존 URl 패턴에 static(정적 파일을 처리하기 위해 그에 맞는 URL 패턴을 반환하는 함수) 함수가 반환하는 URL 패턴 추가
urlpatterns = [
    path('', HomeView.as_view(), name='home'),
    path('admin/', admin.site.urls),
    path('bookmark/', include('bookmark.urls')),
    path('blog/', include('blog.urls')),
    path('photo/', include('photo.urls')),
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT) 

setting.MEDIA_URL로 정의된 /media/ URL 요청이 오면 django.views.static.serve() 뷰 함수가 처리하고, 이 뷰 함수에 document_root = settings.MEDIA_ROOT 키워드 인자가 전달된다.

static.serve() 함수는 개발용이고 상용에는 httpd, nginx 등의 웹 서버 프로그램을 사용한다.

photo/urls.py

app_name = 'photo'

urlpatterns = [
    # /photo/
    path('', views.AlbumLV.as_view(), name='index'),

    # /photo/album/
    path('album/', views.AlbumLV.as_view(), name='album_list'),

    # /photo/album/99
    path('album/<int:pk>/', views.AlbumDV.as_view(), name='album_detail'),

    # /photo/photo/99/
    path('photo/<int:pk>/', views.PhotoDV.as_view(), name='photo_detail'),
]

View 코딩

class AlbumLV(ListView):
    model = Album

class AlbumDV(DetailView):
    model = Album

class PhotoDV(DetailView):
    model = Photo

템플릿 코딩

뷰에서 템플릿 파일명을 지정하지 않았으므로 디폴트 템플릿 명인 album_list.html, album_detail.html, photo_detail.html을 작성한다.

album_list.html

각 앨범에 대한 앨범 정보와 앨범에 속한 사진 5개를 보여주는 화면

album_detail.html

특정 앨범에 들어 있는 사진을 모두 출력하는 템플릿

photo_detail.html

특정 사진에 대한 정보를 출력하는 화면

{% extends "base.html" %}

{% block title %}photo_detail.html{% endblock %}

{% block content %}
    <h2 class="mt-5">{{ object.title }}</h2>

    <div class="row">
      	<-- 원본 이미지 -->
        <div class="col-md-9">
            <a href="{{ object.image.url }}">
                <img src="{{ object.image.url }}" style="width: 100%;">
            </a>
        </div>

        <ul class="col-md-3 mt-3">
            <li class="h5">Photo Description</li>
                {% if object.description %}
                    <p>{{ object.description|linebreaks }}</p>
                {% else %}
                    <p>(blank)</p>
                {% endif %}

            <li class="h5">Date Uploaded</li>
                <p class="font-italic">{{ object.upload_dt }}</p>
            <li class="h5">Album Name</li>
                <p class="font-italic">
                    <a href="{% url 'photo:album_detail' object.album.id %}">
                        {{ object.album.name }}
                    </a>
                </p>
        </ul>
    </div>

{% endblock %}

base.html 수정

photo:index로 향하는 url 추가

<li class="nav-item mx-1 btn btn-primary">
                        <a class="nav-link" text-white href="{% url 'photo:index' %}">Photo</a>
                    </li>

썸네일 만들기 수정

기존에 PIL을 이용해 썸네일을 만들었는데 django-imagekit을 이용하면 더 간단하게 만들 수 있다.

  1. pip install django-imagekit
  2. settings.py에 imagekit 추가
  3. models.py 수정
class Photo(models.Model):
    album = models.ForeignKey(Album, on_delete=models.CASCADE)
    title = models.CharField('TITLE', max_length=30)
    description = models.TextField('Photo Description', blank=True)
    image = models.ImageField(upload_to='photo/%Y/%m')
    image_thumbnail = ImageSpecField(source='image',
                                     processors=[ResizeToFill(1024,1024)],
                                     format='JPEG')
    upload_dt = models.DateTimeField('Upload Date', auto_now_add=True)

    class Meta:
        ordering = ('title',)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('photo:photo_detail', args=(self.id,))

ResizeToFill의 값을 높여주니까 썸네일의 화질이 좋아지는 것을 발견!
대신 로딩 속도가 좀 느려진 것 같기도..?

  1. template에서 photo.image_thumbnail.url로 사용





출처: Django로 배우는 파이썬 웹 프로그래밍(실전편) - 김석훈님
https://sss20-02.tistory.com/40

좋은 웹페이지 즐겨찾기