기타/연산자

파이썬 장고 포토앱 만들기

공부하는리아 2021. 1. 12. 16:08

1. 모델 정의

class Album(models.Model):
    name = models.CharField(max_length=30)
    description = models.CharField('One Line Description', max_length=100, blank = True)
    owner = models.ForeignKey('auth.User', on_delete=models.CASCADE, verbose_name='OWNER', blank=True, null=True)
    
    class Meta:
        ordering = ('name', )
            
    def __str__(self):
        return self.name
    
    def get_absolute_url(self):
        return reverse('photo:album_detail', args=(self.id,)) 
    
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 = ThumbnailImageField(upload_to='photo/%Y/%m')
    upload_dt = models.DateTimeField('Upload Date', auto_now_add=True)
    owner = models.ForeignKey('auth.User', on_delete=models.CASCADE, verbose_name='OWNER', blank=True, null=True)
    
    class Meta:
        ordering = ('title', )
    
    def __str__(self):
        return self.title
    
    def get_absolute_url(self):
        return  reverse('photo:photo_detail', args=(self.id,))

Album 클래스

name = 모델의 이름을 정의

description = 설명 글을 쓰는 곳

odering  = 순서는 '컬럼이름' 기준으로 오름차순

 

Photo 클래스

album = 앨범 아이디를 포링키로 설정

title = 사진 제목 정의

description = 사진 설명을 쓰는 필드

image = 커스텀 필드를 사용해  업로드시 년/월을 표시

upload_dt = 날짜 정의 필드 auto_now_add를 이용 사진이 업로드 되는 시간 자동 기록

 

 

2. 관리자 정의

class PhotoInline(admin.StackedInline):
    model = Photo
    extra = 2
    
@admin.register(Album)
class AlbumAdmin(admin.ModelAdmin):
    inlines = (PhotoInline,)
    list_display = ('id', 'name', 'description')
    
@admin.register(Photo)
class PhotoAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'upload_dt')

inlinse = 앨범객체를 수정 화면을 보여줄 때 ( )안 클래스에서 저의한 사항을 같이 보여준다

 

 

3. fields 정의

import os
from PIL import Image
from django.db.models.fields.files import ImageField, ImageFieldFile

class ThumbnailImageFieldFile(ImageFieldFile):
    def _add_thumb(self, s):
        parts = s.split(".")
        parts.insert(-1, "thumb")
        if parts[-1].lower() not in ['jpeg', 'jpg']:
            parts[-1] = 'jpg'
        return ".".join(parts)
    
    @property
    def thumb_path(self):
        return self._add_thumb(self.path)
        
    @property
    def thumb_url(self):
        return self._add_thumb(self.url)

    def save(self, name, content, save=True): #파일시스템에 파일을 저장하고 생성하는 메서드
        super().save(name, content, save) #부모 ImageFieldFile클래스의 save()메서드를 호출해서 원본 이미지를 저장.

        img = Image.open(self.path)
        size = (self.field.thumb_width, self.field.thumb_height)
        img.thumbnail(size) #PIL 라이브러리의 썸네일 만드는 함수임. Image.thumbnail()이라는 함수를 이용하여 썸네일 제작.
        background = Image.new('RGB', size, (255, 255, 255))
        box = (int((size[0]- img.size[0]) / 2), int((size[1] - img.size[1]) / 2))
        background.paste(img, box)
        background.save(self.thumb_path, 'JPEG') #img와 box를 함쳐 만든 최종 썸네일을 JPEG형식으로 thumb_path 경로에 저장.

    def delete(self, save=True): #원본과 썸네일을 모두 삭제.
        if os.path.exists(self.thumb_path):
            os.remove(self.thumb_path)
        super().delete(save)
        
class ThumbnailImageField(ImageField):
    attr_class = ThumbnailImageFieldFile
    
    def __init__(self, verbose_name=None, thumb_width=250, thumb_height=250, **kwargs):
        self.thumb_width, self.thumb_height = thumb_width, thumb_height
        super().__init__(verbose_name, **kwargs)