장고:사진 올리기: 두 판 사이의 차이

학교의 모든 지식. SMwiki
둘러보기로 이동 검색으로 이동
 
(사용자 2명의 중간 판 14개는 보이지 않습니다)
1번째 줄: 1번째 줄:
{{장고}}
{{장고}}
==개요==
사진을 올리고 관리하기 위해선 모델을 하나 만들어 개별적인 관리가 필요하다.


<br />
<br />
=모델 작성=
글쓰기를 구현했다면 글쓰기 모델에 약간의 변형을 주어보자. 아래의 image필드를 추가한다.


/앱/models.py 안에 작성한다.<syntaxhighlight lang="python">
==탬플릿 변경==
from django.contrib.auth.models import User
from django.db import models
 
class Question(models.Model):#세부내용은 필요에 따라..
 
    image=models.ImageField(upload_to='images/%Y/%m/%d', default='images/no_image.png')
#setting 값에 지정된 상대경로를 사용하기 위해 경로 처음엔 /를 두지 않는다.
</syntaxhighlight>upload_to는 저장할 경로를 정하는 것, default는 이미지 업로드가 되어있지 않을 때 사용할 것을 의미한다.
 
===pillow 설치===
모델을 반영하기 위해 makemigrations를 실행하면 에러가 뜬다. HINT로 pillow를 설치하라는 메시지가 뜬다. 메시지 그대로 <code>python -m pip install Pillow</code>를 입력하자.
 
==각종 사전설정==
 
===업로드 폴더 설정===
settings.py에 MEDIA_ROOT를 다음과 같이 설정한다.(기본설정이 없기 때문에 새로 써주어야 한다.)<syntaxhighlight lang="python">
MEDIA_URL='/media/' #미디어 파일을 불러올 때 사용할 가상 url을 설정한다.
 
MEDIA_ROOT=BASE_DIR / 'media' #기본프로젝트 하위의 media에서 모든 업로드 매체를 관리한다.
#media 하위에 앱이름으로 디렉터리를 만들고 파일을 업로드하게 된다.
</syntaxhighlight>유저가 업로드한 파일이 모두 여기에서 관리된다.
 
== 탬플릿 변경 ==


===등록 만들기===
===등록 만들기===
41번째 줄: 11번째 줄:
     <input type="file" name="image" id="image" accept="image/*" value="{{ form.image.value|default_if_none:''}}">
     <input type="file" name="image" id="image" accept="image/*" value="{{ form.image.value|default_if_none:''}}">
</form>
</form>
</syntaxhighlight>수정페이지의 탬플릿도 그대로 사용하면 되는데, 필요에 따라 '등록하기'를 '수정하기'로 바꾼다든가 간단한 조작만 하면 된다.
</syntaxhighlight><br />
<br />
===상세 페이지 변경===
===상세 페이지 변경===
이미지가 보이는 곳은 상세화면이므로 detatil.html을 수정한다. 적당한 자리에 다음과 같은 형태로 끼워넣는다. image 속성 하위엔 url 속성이 있어 이를 통해 이미지를 가져온다.<syntaxhighlight lang="html+django">
이미지가 보이는 곳은 상세화면이므로 detatil.html을 수정한다. 적당한 자리에 다음과 같은 형태로 끼워넣는다. image 속성 하위엔 url 속성이 있어 이를 통해 이미지를 가져온다.<syntaxhighlight lang="html+django">
52번째 줄: 21번째 줄:
</syntaxhighlight>
</syntaxhighlight>


==== urls.py 수정 ====
==라우팅==
<nowiki>{{ user.profile.image.url }}</nowiki> 형태로 이미지를 불러오기도 한다. 모델의 속성에 이미지를 넣으면, 속성.url 형태로 내용을 불러올 수 있다.
 
그런데, 위처럼 url로 불러올 때엔 urls.py에 라우팅해주어야 한다.
 
====urls.py 수정(혹시 외부서버에 연결해 사용할 요량이라면 필요 없다.)====
보통 여기까지 하면 관리자페이지에서 사진을 올려 확인하는 과정을 거친다. 그런데, 위처럼 해서 이미지를 등록해도 이미지가 보이지 않는데, 이는 urls.py에 미디어 경로가 등록되지 않았기 때문이다.
보통 여기까지 하면 관리자페이지에서 사진을 올려 확인하는 과정을 거친다. 그런데, 위처럼 해서 이미지를 등록해도 이미지가 보이지 않는데, 이는 urls.py에 미디어 경로가 등록되지 않았기 때문이다.


때문에 이를 위해 최상단의 urls.py에 다음과 같은 내용을 추가해준다.(기존 urlpatterns의 하단에)<syntaxhighlight lang="python">
때문에 이를 위해 최상단의 urls.py의 urlpatterns에 다음과 같은 내용을 추가해준다.(기존 urlpatterns의 하단에)<syntaxhighlight lang="python">
from django.conf.urls.static import static
from django.conf.urls.static import static
from django.conf import settings
from django.conf import settings


urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
</syntaxhighlight>그런데, 이건 디버그모드가 True일 때에만 작동한다.[아닐 땐 어떻게 해? 서비스 모드에선?]
</syntaxhighlight>그런데, 이건 디버그모드가 True일 때에만 작동한다. 이것은 확인용으로, 외부서버와 연결한 후에는 지워버린다.
<br />
 
=이미지 리사이징 및 포멧 변경=
==django-imagekit==
고용량의 이미지를 올릴 때 이미지 목록에선 이미지 전체가 아닌, 썸네일을 보여주는 편이 경제적이다. 혹은 사진을 흑백사진으로 만든다든가, 용량을 바꾼다든가, 사진의 불필요한 부분을 다듬는다든가 간단한 조작이 필요할 때 사용하는 패키지이다.
 
기존에 사용하던 이미지 모델이 있더라도 적용하면 /media/CACHE 디렉터리 안에 기존 디렉터리 경로와 같은 형태로 썸네일을 만든다.
{| class="wikitable"
!과정
!설명
!방법
|-
|설치
|사전에 PIL이나 Pillow같은 이미지 조작툴이 설치되어 있어야 한다.
django-imagekit과 imagekit은 다르니 혼동하지 않도록 유의.
|pip install django-imagekit
|-
|등록
|settings.py의 app 목록에 등록한다.
|INSTALLED_APPS 하위에 'imagekit' 추가
|}
이후.
 
===모델작성===
다음 코드는 https://pypi.org/project/django-imagekit/<nowiki/>에서 공개된 코드를 변형한 것이다.
{| class="wikitable"
!과정
!설명
!방법
|-
|모델
|모델작성을 통해 활용하는 게 가장 쉬운 방법.
원본 이미지도 함께 저장한다.
 
 
섬네일은 /media/CACHE/ 디렉터리에 저장된다.
{| class="wikitable"
|+processors 옵션
!옵션
!설명
|-
|ResizeToFill
|해당 크기에 채워 리사이징.(넘친 부분 잘라 크기 통일)
|-
|<code>ResizeToFit</code>
|해당 크기안에 들어오게 리사이징.(원본비율 유지)
|-
|
|
|}
|<syntaxhighlight lang="python">
from django.db import models  # 기존 모델에서 사용.
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill
 
class Profile(models.Model):
    avatar = models.ImageField(upload_to='avatars')
    avatar_thumbnail = ImageSpecField(source='avatar',  # 원본의 위치 지정
                                      processors=[ResizeToFill(100, 50)],  # 가로, 세로 순서.
                                      format='JPEG',
                                      options={'quality': 60})
 
profile = Profile.objects.all()[0]
print(profile.avatar_thumbnail.url)    # > /media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg
print(profile.avatar_thumbnail.width)  # > 100
</syntaxhighlight>
|-
|원본 이미지가 필요 없을 때.
|서버용량문제를 생각하면 원본이미지는 버리는 편이 좋다.
|<syntaxhighlight lang="python">
from django.db import models  # 기존 모델에서 사용.
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill
 
class Profile(models.Model):
    avatar_thumbnail = ProcessedImageField(upload_to='avatars',  # 올릴 위치 지정.
                                          processors=[ResizeToFill(100, 50)],
                                          format='JPEG',
                                          options={'quality': 60})
</syntaxhighlight>
|}
 
===팁===
보통 경로를 지정할 때 아래 메서드를 정의해 사용한다.<syntaxhighlight lang="python">
def user_path(self, filename):
    extention = filename.split('.')[-1]  # 파일의 확장자만 추출한다.
    return '경로/{}/{}.{}'.format(self.user.username, 'profile', extention)
</syntaxhighlight>
 
===탬플릿에서의 사용===
{| class="wikitable"
!과정
!설명
!방법
|-
|탬플릿에 삽입
|기존 이미지 사용과 동일하다.
|<nowiki><img src="{{ 모델.이미지가담김필드명.url }}" /></nowiki>
|}
 
===admin 등록===
<syntaxhighlight lang="python">
from django.contrib import admin
from imagekit.admin import AdminThumbnail
from .models import Photo
 
class PhotoAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'admin_thumbnail')
    admin_thumbnail = AdminThumbnail(image_field='thumbnail')
 
admin.site.register(Photo, PhotoAdmin)
</syntaxhighlight>
 
===이외 사용===
위에선 이미지 처리를 모델에서 수행했는데, form에서 처리하고 모델에선 일반 이미지 필드를 사용할 수도 있다.
 
삭제 : 이미지를 수정하면 기존의 이미지는 남아있는 상태에서 새 이미지를 올리게 되는데, 여기에 대한 낭비는 줄여야 하지 않을까??

2023년 2월 6일 (월) 18:19 기준 최신판

장고! 웹 프레임워크! 틀:장고

  1. 장고:개요
  2. 장고:웹페이지설계
    1. 장고:앱
    2. 장고:url
    3. 장고:model
      1. 장고:DB
      2. 장고:모델 필드
      3. 장고:모델의 변경
    4. 장고:view
      1. 장고:클래스형 뷰, 제네릭 뷰
      2. 장고:view 각종 기능
    5. 장고:template
    6. 장고:static. 정적파일 사용하기
      1. 장고:CSS 사용하기
      2. 장고:JS 사용하기
      3. 장고:글꼴 사용
      4. 장고:부트스트랩
    7. 장고:media. 미디어 파일 사용하기
  3. 장고:관리자페이지
  4. 장고:settings.py
  5. 장고:기능구현
    1. 장고:회원관리
    2. 장고:유저
    3. 장고:커스텀 유저
    4. 장고:소셜로그인
    5. 장고:입력받기
    6. 장고:저장된 내용 활용하기
    7. 장고:변수 내보내기
    8. 장고:글쓰기
    9. 장고:페이징(페이지나누기)
    10. 장고:답변쓰기(댓글쓰기)
    11. 장고:추천,즐겨찾기
    12. 장고:새글(최신글) 나타내기
    13. 장고:썸머노트 설치
    14. 장고:네비게이션 바 만들기
    15. 장고:검색기능
    16. 장고:카테고리 만들기
    17. 장고:사진 올리기
    18. 장고:파일 업로드
    19. 장고:이메일app 만들기
    20. 장고:매직 그리드
  6. 장고:웹서비스
    1. 장고:Git
    2. 장고:리눅스에 올리기
    3. 장고:우분투에 올리기(nginx 사용)
    4. 장고:도커로 올리기
  7. 장고:팁


탬플릿 변경[편집 | 원본 편집]

등록 만들기[편집 | 원본 편집]

이미지를 등록하기 위해 create.html을 수정한다.

<form action="", method="post" enctype="multipart/form-data">
<!--enctype="multipart/form-data"를 추가한다. 이는 파일 업로드 때 사용하는 옵션으로, 데이터를 문자열로 인코딩하지 않는다.-->    
    <input type="file" name="image" id="image" accept="image/*" value="{{ form.image.value|default_if_none:''}}">
</form>


상세 페이지 변경[편집 | 원본 편집]

이미지가 보이는 곳은 상세화면이므로 detatil.html을 수정한다. 적당한 자리에 다음과 같은 형태로 끼워넣는다. image 속성 하위엔 url 속성이 있어 이를 통해 이미지를 가져온다.

  {% if question.image %}<!--이미지 속성이 있을 때에만 부른다. 없으면 에러;;-->
    <div>
        <p><img src="{{question.image.url}}" style="width:90%"></p>
    </div>
  {% endif %}

라우팅[편집 | 원본 편집]

{{ user.profile.image.url }} 형태로 이미지를 불러오기도 한다. 모델의 속성에 이미지를 넣으면, 속성.url 형태로 내용을 불러올 수 있다.

그런데, 위처럼 url로 불러올 때엔 urls.py에 라우팅해주어야 한다.

urls.py 수정(혹시 외부서버에 연결해 사용할 요량이라면 필요 없다.)[편집 | 원본 편집]

보통 여기까지 하면 관리자페이지에서 사진을 올려 확인하는 과정을 거친다. 그런데, 위처럼 해서 이미지를 등록해도 이미지가 보이지 않는데, 이는 urls.py에 미디어 경로가 등록되지 않았기 때문이다.

때문에 이를 위해 최상단의 urls.py의 urlpatterns에 다음과 같은 내용을 추가해준다.(기존 urlpatterns의 하단에)

from django.conf.urls.static import static
from django.conf import settings

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

그런데, 이건 디버그모드가 True일 때에만 작동한다. 이것은 확인용으로, 외부서버와 연결한 후에는 지워버린다.


이미지 리사이징 및 포멧 변경[편집 | 원본 편집]

django-imagekit[편집 | 원본 편집]

고용량의 이미지를 올릴 때 이미지 목록에선 이미지 전체가 아닌, 썸네일을 보여주는 편이 경제적이다. 혹은 사진을 흑백사진으로 만든다든가, 용량을 바꾼다든가, 사진의 불필요한 부분을 다듬는다든가 간단한 조작이 필요할 때 사용하는 패키지이다.

기존에 사용하던 이미지 모델이 있더라도 적용하면 /media/CACHE 디렉터리 안에 기존 디렉터리 경로와 같은 형태로 썸네일을 만든다.

과정 설명 방법
설치 사전에 PIL이나 Pillow같은 이미지 조작툴이 설치되어 있어야 한다.

django-imagekit과 imagekit은 다르니 혼동하지 않도록 유의.

pip install django-imagekit
등록 settings.py의 app 목록에 등록한다. INSTALLED_APPS 하위에 'imagekit' 추가

이후.

모델작성[편집 | 원본 편집]

다음 코드는 https://pypi.org/project/django-imagekit/에서 공개된 코드를 변형한 것이다.

과정 설명 방법
모델 모델작성을 통해 활용하는 게 가장 쉬운 방법.

원본 이미지도 함께 저장한다.


섬네일은 /media/CACHE/ 디렉터리에 저장된다.

processors 옵션
옵션 설명
ResizeToFill 해당 크기에 채워 리사이징.(넘친 부분 잘라 크기 통일)
ResizeToFit 해당 크기안에 들어오게 리사이징.(원본비율 유지)
from django.db import models  # 기존 모델에서 사용.
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar = models.ImageField(upload_to='avatars')
    avatar_thumbnail = ImageSpecField(source='avatar',  # 원본의 위치 지정
                                      processors=[ResizeToFill(100, 50)],  # 가로, 세로 순서.
                                      format='JPEG',
                                      options={'quality': 60})

profile = Profile.objects.all()[0]
print(profile.avatar_thumbnail.url)    # > /media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg
print(profile.avatar_thumbnail.width)  # > 100
원본 이미지가 필요 없을 때. 서버용량문제를 생각하면 원본이미지는 버리는 편이 좋다.
from django.db import models  # 기존 모델에서 사용.
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar_thumbnail = ProcessedImageField(upload_to='avatars',  # 올릴 위치 지정.
                                           processors=[ResizeToFill(100, 50)],
                                           format='JPEG',
                                           options={'quality': 60})

[편집 | 원본 편집]

보통 경로를 지정할 때 아래 메서드를 정의해 사용한다.

def user_path(self, filename):
    extention = filename.split('.')[-1]  # 파일의 확장자만 추출한다.
    return '경로/{}/{}.{}'.format(self.user.username, 'profile', extention)

탬플릿에서의 사용[편집 | 원본 편집]

과정 설명 방법
탬플릿에 삽입 기존 이미지 사용과 동일하다. <img src="{{ 모델.이미지가담김필드명.url }}" />

admin 등록[편집 | 원본 편집]

from django.contrib import admin
from imagekit.admin import AdminThumbnail
from .models import Photo

class PhotoAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'admin_thumbnail')
    admin_thumbnail = AdminThumbnail(image_field='thumbnail')

admin.site.register(Photo, PhotoAdmin)

이외 사용[편집 | 원본 편집]

위에선 이미지 처리를 모델에서 수행했는데, form에서 처리하고 모델에선 일반 이미지 필드를 사용할 수도 있다.

삭제 : 이미지를 수정하면 기존의 이미지는 남아있는 상태에서 새 이미지를 올리게 되는데, 여기에 대한 낭비는 줄여야 하지 않을까??