사진들을 앨범으로 그룹화해 관리하고 각 사진에 대한 정보를 등록하고 열람할 수 있는 Photo 앱 개발
사진의 썸네일을 처리하기 위해 새로운 커스텀 필드가 필요하므로, Pillow 라이브러리를 활용해서 커스텀 필드를 작성해야 한다.
Album 테이블
Photo 테이블
하나의 앨범은 여러 개의 사진을 가질 수 있고, 하나의 사진은 하나의 앨범에만 속할 수 있으므로 다음 관계가 성립한다.
Album 테이블- 1 : N -Photo 테이블
python manage.py startapp photo
'photo.apps.PhotoConfig',
models.py
외래 키로 연결된 Album, Photo 테이블 간에는 1:N 관계이므로 앨범 객체를 보여줄 때 객체에 연결된 사진 객체들을 같이 보여준다. 같이 보여주는 형식은 세로로 나열되는 형식인 Stackedlnline과 테이블 모양처럼 행으로 나열되는 형식인 Tabularlnline이 있다.
사진을 저장하기 위한 필드인 ThumbnailImageField 커스텀 필드 작성
커스텀 필드를 작성할 때는 기존의 비슷한 필드를 상속받아 작성하는 것이 보통으로 이미지 관련 커스텀 필드는 ImageField 클래스를 상속받아 작성한다. ImageField 필드는 이미지 파일을 파일 시스템에 쓰고 삭제하는 작업이 필요하므로, ImageFieldFile 클래스가 필요하고 두 클래스를 연계시켜주는 코드도 필요하다.
두 개의 테이블을 신규로 정의했으니까 DB에 반영해준다.
admin.py 파일에 정의된 StackedInline 설정에 따라, 입력 양식이 세로로 추가되는 방식으로 extra 설정에 따라 앨범 하나에 사진 2개를 입력할 수 있는 형식이다.
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 등의 웹 서버 프로그램을 사용한다.
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'),
]
class AlbumLV(ListView):
model = Album
class AlbumDV(DetailView):
model = Album
class PhotoDV(DetailView):
model = Photo
뷰에서 템플릿 파일명을 지정하지 않았으므로 디폴트 템플릿 명인 album_list.html, album_detail.html, photo_detail.html을 작성한다.
각 앨범에 대한 앨범 정보와 앨범에 속한 사진 5개를 보여주는 화면
특정 앨범에 들어 있는 사진을 모두 출력하는 템플릿
특정 사진에 대한 정보를 출력하는 화면
{% 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 %}
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을 이용하면 더 간단하게 만들 수 있다.
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의 값을 높여주니까 썸네일의 화질이 좋아지는 것을 발견!
대신 로딩 속도가 좀 느려진 것 같기도..?
출처: Django로 배우는 파이썬 웹 프로그래밍(실전편) - 김석훈님
https://sss20-02.tistory.com/40