1) Posts App
포스트와 관련된 기능들을 구현할 어플리케이션
1-1. OverView
-
Post 모델 작성
- 1:N relation - 유저 <-> Post
- M:N relation - 좋아요 클릭한 유저 <-> Post
-
Media file을 업로드하기 위한 장치들 마련
-
ImageField를 통해 Image의 url을 저장할 column 만들기
-
- 사용자가 제공한 파일(binary code)를 인코딩하는 작업 수행
-
enctype = “multipart/form-data”
-
인코딩한 파일을 서버에 저장하기
- MEDIA_ROOT, MEDIA_URL
- request.FILES
-
저장된 파일을 사용자가 조회할 수 있게 url 안내하기
- static
-
1-2. Post Model
-
Post 모델
Column Description Content 내용, charfield Image 이미지 url을 정의, imagefield User 작성자, Foreignkey Like_users 좋아요를 클릭한 유저들, ManyToManyField from django.db import models from django.conf import settings from django.contrib.auth import get_user_model # Create your models here. class Post(models.Model): content = models.CharField(max_length=150) image = models.ImageField(blank=True) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) like_users = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="like_posts", blank=True)
좋아요기능과 작성자<->포스트 기능을 위해서는 1:N, M:N relation이 필요한데 다음 포스트에서 설명하도록 하겠습니다. 일단 이번에는 이미지 업로드 기능만 구현하도록 하겠습니다.
1-3. Image Upload
-
이미지를 관리할 Column
- ImageField(upload_to=None, height_field=None, width_field=None, max_length=100, **options)
-
테이블에 Image 그자체를 저장하지는 않고, Image가 저장된 곳의 url을 저장하는 Column
-
- Pillow 라이브러리를 필요로 함.
-
Python Imaging Library
-
매개변수들
-
upload_to : 어디에 저장될지를 정해줌.
class MyModel(models.Model): # file will be uploaded to MEDIA_ROOT/uploads upload = models.FileField(upload_to='uploads/') # or... # file will be saved to MEDIA_ROOT/uploads/2015/01/30 upload = models.FileField(upload_to='uploads/%Y/%d/')
-
Image Processing을 위하여 height와 width를 정의하기 위한 field도 필요하지만,
나중에 다루도록 하겠습니다.
-
-
파일이 전송되는 방식
- 파일을 업로드
- 업로드된 파일을 인코딩
- 특정 주소에 파일을 저장함
- 디비에는 저장된 주소를 저장함.
- 파일을 업로드
-
- 사용자가 보낸 파일을 인코딩하는 작업을 수행
HttpRequest.
FILES
¶A dictionary-like object containing all uploaded files. Each key in
FILES
is thename
from the<input type="file" name="">
. Each value inFILES
is anUploadedFile
.See Managing files for more information.
FILES
will only contain data if the request method was POST and the<form>
that posted to the request hadenctype="multipart/form-data"
. Otherwise,FILES
will be a blank dictionary-like object.아무튼 POST 메서드로 파일을 받을거면, 인코딩을 선언해줘야한다고 합니다.
<form method="POST" enctype="multipart/form-data"> {% csrf_token %} {{form.as_p}} <!-- ModelForm을 통하여 form을 제작 --> <button type="submit"> 제출 </button> </form>
-
인코딩된 파일을 서버에 저장하기
이 부분은 Django reference에 잘 설명되어 있습니다.
Using a
FileField
or anImageField
(see below) in a model takes a few steps:- In your settings file, you’ll need to define
MEDIA_ROOT
as the full path to a directory where you’d like Django to store uploaded files. (For performance, these files are not stored in the database.) DefineMEDIA_URL
as the base public URL of that directory. Make sure that this directory is writable by the Web server’s user account. - Add the
FileField
orImageField
to your model, defining theupload_to
option to specify a subdirectory ofMEDIA_ROOT
to use for uploaded files. - All that will be stored in your database is a path to the file (relative to
MEDIA_ROOT
). You’ll most likely want to use the convenienceurl
attribute provided by Django. For example, if yourImageField
is calledmug_shot
, you can get the absolute path to your image in a template with ``.
For example, say your
MEDIA_ROOT
is set to'/home/media'
, andupload_to
is set to'photos/%Y/%m/%d'
. The'%Y/%m/%d'
part ofupload_to
isstrftime()
formatting;'%Y'
is the four-digit year,'%m'
is the two-digit month and'%d'
is the two-digit day. If you upload a file on Jan. 15, 2007, it will be saved in the directory/home/media/photos/2007/01/15
.내용을 요약하면,
- MEDIA_ROOT : 쟝고가 업로드된 파일을 저장할 full path
- upload_to 옵션을 통해서 subdirectory를 특정할 수 있음.
- 보통은 작업속도를 빠르게 하기 위해서 날짜/시간과 같이 변하는 값으로 디렉토리를 구분해서 저장하는경우가 많음.
- upload_to 옵션을 통해서 subdirectory를 특정할 수 있음.
- MEDIA_URL : 그 디렉토리의 base public URL로 지정하여라.
- 그렇게 저장된 image에서 object.이미지필드명.url 을 입력하면 절대경로를 얻을 수 있음.
그래서,
먼저 MEDIA_ROOT와 MEDIA_URL을 지정합니다.
# settings.py MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # full path MEDIA_URL = '/media/' # base public URL
두번째로는 view에서 ModelForm을 통해서 File을 받겠다는 것을 명시해줘야 합니다.
# views.py def Upload(request, post_id): post = get_object_or_404(Post, id=post_id) if request.method == "POST": ###############이 부분이 핵심 post_form = PostModelForm(request.POST, request.FILES) # 유효성 검사 후 저장 else: # ... # 빈 FORM을 보여주는 페이지 렌더링
- In your settings file, you’ll need to define
-
지정한 파일을 사용자가 볼 수 있게 URL을 안내하기
MEDIA_URL / 이미지파일 이름.jpg 의 형식으로 파일에 접근할 수 있습니다.
하지만, url_dispatcher의 허락을 받아야 하기 때문에 다음과 같은 설정을 필요로 합니다.
Serving files uploaded by a user during development
이 링크에서는 static() 함수를 사용하는데, 이 함수는 디버그모드에서 파일을 serve할 url들을 리턴하는 함수입니다.
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # ... the rest of your URLconf goes here ... ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)