[Django/파일 업로드 구현]

SooYeon Yeon·2022년 6월 26일
0

Django

목록 보기
14/20

파일 업로드 구현하기

1. pillow 설치

파이썬 이미지 사용을 위해 pillow 설치

pip install pillow

2. 모델에 image 추가

from django.db import models

# Create your models here.
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=40)
    contents = models.TextField()
    image = models.ImageField(upload_to='images/', blank=True, null=True) # null은 DB관련 설정(null가능하게), blank는 입력양식쪽과 관련(form에 입력안해도 됨)

#이미지 있는 게시판이랑 없는 게시판이랑 따로 있으면 이렇게 모델로 따로 두는거 나음
# class PostImage(models.Model):
#    image = models.ImageField
#    post = models.On

3. settings.py

static url 밑에

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

하고 media 디렉토리 생성

모델 변경되었으니 migrate해줌

4. postForm 추가

postForm에도 image추가

from django import forms

from board.models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ('title', 'contents','image',)

5. html

파일과 텍스트 같이보내니까 form에서 enctype해서 전달해줘야함 (http의 헤더 바꿔주는거)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
{{ postForm }}
<button>제출</button>
</form>
</body>
</html>

6. urls.py

from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include

import accounts.views
import board.views
from config import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/',include('allauth.urls')),
    path('test',accounts.views.func1),
    path('kakaologin',accounts.views.kakaoLoginPage),
    path('oauth/redirect',accounts.views.getcode),
    path('accounts/profiles/',accounts.views.profile),
    path('board/create',board.views.create),
    path('board/list',board.views.list),

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

7. html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if post%}
    제목 : {{ post.title }} <br>
    내용 : {{ post.contents }}
    이미지 : <img src="/media/{{ post.image }}">
{% endif %}
</body>
</html>

사용자랑 프로필 하고싶으면 User모델에다가

image = models.ImageField(upload_to='images/', blank=True, null=True) 추가하면 됨

8. (또 다른 방법) PostImage Model 만들어서 사용

원래 했던거처럼 PostImage를 model로 만들어하고싶으면 Post모델밑에다가 이렇게 하고 PostForm에 image는 지우기

class PostImage(models.Model):
	image = models.ImageField(upload_to='images/', blank=True, null=True)
	post = models.ForeignKey(Post, on_delete=models.CASCADE)

모델을 따로 만들고 Post를 기준으로 뽑을때 없으면 prefetched related임 역방향

9. html - multipl

그러고 multiple할수있게 함

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
{{ postForm }}
    <input multiple type="file" name="image" accept="image/*" id="id_image">
<button>제출</button>
</form>
</body>
</html>

10. views.py

from django.shortcuts import render, redirect

# Create your views here.
from board.forms import PostForm, PostFormImage
from board.models import Post, PostImage

def create(request):
    if request.method == "GET":
        postForm = PostForm()
        context = {'postForm' : postForm}
        return render(request,'board/create.html',context)
    elif request.method == "POST":
        postForm = PostForm(request.POST)

        if postForm.is_valid():
            post = postForm.save(commit=False)
            post.save()
            # 파일은 request.POST에 안오고 request.FILES에 오니까 따로 처리
            for image in request.FILES.getlist('image',None):
                postImage = PostImage()
                postImage.image = image
                postImage.post = post
                postImage.save()

        return redirect('board/read/'+str(post.id))

def read(request,bid):
    post = Post.objects.prefetch_related('postimage_set').get(id=bid)  # Q (장고에 있는 모델) 이용해서 하나만 조회 가능 (filter은 for문 해야하는데 이 경우 하나만 가능)
    postImageForm = PostFormImage()
    context = {
        'post': post,
        'ImageForm':postImageForm,
    }
    print(context)
    return render(request, 'board/read.html', context)

11. html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
ㅋㅋ
{% for postimage in post.postimage_set.all %}
    제목 : {{ post.title }} <br>
    내용 : {{ post.contents }}
    이미지 : <img src="/media/{{ postimage.image }}">
{% endfor %}

</body>
</html>

이렇게하면 여러개 가져올수있다

이미지를 누르면 100장 다 되는 방법 vs 게시글을 작성하는 동안에 미리 저장하고있는 거 하면 빠름

0개의 댓글