[웹 프로그래밍 기초] 게시판에 이미지 업로드해서 불러오기

2020. 6. 22. 13:56노트/Django : 웹

 

 

 

 

  • Terminal 에서 formclass 폴더로 이동 

  • 가상환경 세팅해서 django 설치하기 
python -m venv venv
source venv/Scripts/activate
python manage.py startapp pages
pip install django==2.2.13

 

 

  • models.py가 변경되면 마이그레이션 하기 
python manage.py makemigrations
python manage.py migrate 

 

  • 이미지랑 관련된 django 라이브러리 설치하기 
pip install pilkit django-imagekit

 

code 

  • detail.html 파일에 이미지 업로드 코드 추가 

{% extends 'base.html' %}

{% load static %}

{% block body %}

<h1>Article Detail</h1>


<p>PK: {{ article.pk }}</p>
<p>제목: {{ article.title }}</p>
<p>내용: {{ article.content }}</p>
{% if article.image %}
    <p>
        이미지: <img src ="{{ article.image.url }}" alt = "{{ article.image}}"> 
    </p>>
{% endif %}
<p>생성 시각: {{ article.created_at }}</p>
<p>수정 시각: {{ article.updated_at }}</p>

<a href="{% url 'articles:index' %}">Index</a>
<a href="{% url 'articles:edit' article.pk %}">Edit</a>

<form action="{% url 'articles:delete' article.pk %}" method="POST">
    {% csrf_token %}
    <input type="submit" value="Delete">
</form>

<!-- 댓글 목록 -->
<h3>댓글 목록 ({{ article.comment_set.all.count }})</h3>
<!-- |length , .count -->
<ul>
    {% for comment in article.comment_set.all %}
    <li>
        {{ comment.content }} - {{ comment.created_at }}
        <a href="{% url 'articles:comments_edit' article.pk comment.pk %}">Edit</a>
        <form action="{% url 'articles:comments_delete' article.pk comment.pk %}" method="POST">
            {% csrf_token %}
            <input type="submit" value="Delete">
        </form>
    </li>
    {% empty %}
    <li>
        작성된 댓글이 없습니다 :(
    </li>
    {% endfor %}
</ul>

<!-- 댓글 입력창 -->
<h3>댓글 입력</h3>
<form action="{% url 'articles:comments_new' article.pk %}" method="POST">
    {% csrf_token %}
    {{ comment_form }}
    <input type="submit">
</form>

{% endblock %}

 

  • settings.py >  INSTALLED_APPS > 맨 아래 imagekit  추가 

 

 

  • settings.py > 맨 아래 이미지 파일 위치 설정, 이미지 주소 생성 코드 설정

# Media files 

1. 업로드 되는 이미지 파일 위치를 정하는 설정 

MEDIA_ROOT = os.path.join(BASE_DIR,'media')

2. 업로드 된 이미지의 주소를 생성하는 설정 

MEDIA_URL = '/media/' # 아무거나 해도 됌

3. urls.py 

 

 

  • urls.py에 MEDIA_ROOT , MEDIA_URL 추가 
  • settings 와 static을 불러오기

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


urlpatterns = [
    path('admin/', admin.site.urls),
    path('articles/', include('articles.urls')),
]

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

 

  • index.html에 정적 이미지 파일 불러오기 

{% extends 'base.html' %}

{% load static %}

{% block body %}

<h1>Article Index</h1>

<a href="{% url 'articles:new' %}">New</a>

<ul>
    {% for article in articles %}
        <li>
            <a href="{% url 'articles:detail' article.pk %}">{{ article.title }}</a>
        </li>
    {% endfor %}
</ul>

<img src ="{% static 'main.png' %}" alt="보노보노">

{% endblock %}

 

 

  • json 파일 웹페이지로 load하기 
python manage.py dumpdata articles.article --indent=2 > article.json 
python manage.py loaddata article.json 

 

# Django Fixtures 

 1. dumpdata

python manage.py dumpdata articles.article --indent=2 > article.json

 

 2. loaddata 

python manage.py loaddata article.json 

 

 3. csv to  fixtures

http://hpy.hk/c2f

 

 

  • models.py에 이미지 파일 기본 세팅 설정해주기 

from django.db import models
from imagekit.models import ProcessedImageField
from imagekit.processors import Thumbnail

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=10)
    content = models.TextField()
    # image = models.ImageField(blank=True) #None(null) vs. 0, ''
    image = ProcessedImageField(
                            blank=True,
                            processors=[ # 어떤 가공을 할지 
                                Thumbnail(300, 300),
                            ], 
                            format='JPEG', # 이미지 포멧 (jpg, png)
                            options={  # 이미지 포멧 관련 옵션 
                                'quality':90,
                            }
                        )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

 

  • forms.py에 ArticleForm>Meta > fields > 'image' 추가 

from django import forms
from .models import Article, Comment


class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ('title', 'content', 'image',)


class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('content',)

 

  • new.html에 이미지 업로드 할 수 있는 line 생성하기

{% extends 'base.html' %}

{% block body %}

<h1>Article New</h1>

<form action="" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <!-- <label for="title">제목</label>
    <input id="title" type="text" name="title">
    <label for="content">내용</label>
    <textarea id="content" name="content" id="" cols="30" rows="10"></textarea> -->
    <input type="submit">
</form>


{% endblock %}

 

  • views.py 에 이미지파일 불러올 수 있는 경로 설정 

아래 코드 추가

def new(request):
    if request.method == 'POST':
    form = ArticleForm(request.POST, request.FILES)

전체 views.py 코드 

from django.shortcuts import render, redirect
from .models import Article, Comment
from .forms import ArticleForm, CommentForm

# Create your views here.
def index(request):
    articles = Article.objects.all()
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index.html', context)

def new(request):
    if request.method == 'POST':
        # Database에 저장
        # 1. 요청에 실려온 data 꺼내오기
        # title = request.POST.get('title')
        # content = request.POST.get('content')
        # image = request.FILES.get('image')
        form = ArticleForm(request.POST, request.FILES)
        
        # 2-1. data 유효성 검사
        if form.is_valid():
            # (ModelForm) 2-2. Database에 저장
            article = form.save()
            # # 2-2. 검증된 data 꺼내오기
            # title = form.cleaned_data.get('title')
            # content = form.cleaned_data.get('content')
            # # 2-3. Database에 저장
            # article = Article(title=title, content=content)
            # article.save()
            # 3. 저장된 data를 확인할 수 있는 곳으로 안내
            return redirect('articles:detail', article.pk)

    else: # GET
        # 작성 양식 보여주기
        form = ArticleForm()
    context = {
        'form': form,
    }
    return render(request, 'articles/new.html', context)


def detail(request, pk):
    # Database에서 data 가져오기
    article = Article.objects.get(pk=pk)

    # 댓글 작성 양식 가져오기
    comment_form = CommentForm()

    context = {
        'article': article,
        'comment_form': comment_form,
    }
    return render(request, 'articles/detail.html', context)


def delete(request, pk): # POST
    article = Article.objects.get(pk=pk)
    if request.method == 'POST':
        article.delete()
    return redirect('articles:index')

def edit(request, pk):
    # 1. Database에서 data 가져오기
    article = Article.objects.get(pk=pk)

    if request.method == 'POST':
        # data 수정!
        
        # (ModelForm) 2-1. form에 data 집어넣기 + instance와 연결
        form = ArticleForm(request.POST, instance=article)
        # # 2-1. form에 data 집어넣기(검증 목적)
        # form = ArticleForm(request.POST)
        # 2-2. form에서 data 유효성 검사
        if form.is_valid():
            # (ModelForm) 2-3. Database에 저장
            article = form.save()
            # # 2-3. 검증된 data를 반영하기(저장)
            # article.title = form.cleaned_data.get('title')
            # article.content = form.cleaned_data.get('content')
            # article.save()
            # 3. 저장된 내용을 확인할 수 있는 페이지로 안내
            return redirect('articles:detail', article.pk)
    else:  
        # 수정 양식 보여주기!
        # (ModelForm) 2. Form에 data 채워 넣기
        form = ArticleForm(instance=article)
        # # 2. Form에 data 채워 넣기
        # form = ArticleForm(initial=article.__dict__)
    context = {
        'form': form,
    }
    return render(request, 'articles/edit.html', context)


def comments_new(request, article_pk): # POST
    # 1. 요청이 POST인지 점검
    if request.method == 'POST':
        # 2. form에 data를 집어넣기 (목적 == 유효성 검사)
        # request.POST #=> { 'content': '와 댓글!' }
        form = CommentForm(request.POST)
        # 3. form에서 유효성 검사를 시행
        if form.is_valid():
            # 4. 통과하면 database에 저장(?)
            comment = form.save(commit=False)
            # 4-1. article 정보 주입
            comment.article_id = article_pk
            comment.save()
    # 5. 생성된 댓글을 확인할 수 있는 곳으로 안내
    return redirect('articles:detail', article_pk)


def comments_delete(request, article_pk, pk): # POST
    # 0. 요청이 POST인지 점검
    if request.method == 'POST':
        # 1. pk를 가지고 삭제하려는 data 꺼내오기
        comment = Comment.objects.get(pk=pk)
        # 2. 삭제
        comment.delete()
    # 3. 삭제되었는지 확인 가능한 곳으로 안내
    return redirect('articles:detail', article_pk)


def comments_edit(request, article_pk, pk): # GET, POST
    # Database에서 수정하려 하는 data 가져오기
    comment = Comment.objects.get(pk=pk)
    # 0. 요청의 종류가 POST인지 GET인지 점검
    if request.method == 'POST':
        # 실제로 수정!
        # 1. form에 '넘어온 data' & '수정하려는 data' 집어넣기
        form = CommentForm(request.POST, instance=comment)
        # 2. 유효성 검사
        if form.is_valid():
            # 3. 검사를 통과했다면, save
            comment = form.save()
            # 4. 변경된 결과 확인하는 곳으로 안내
            return redirect('articles:detail', article_pk)
    else:
        # 수정 양식 보여주기!
        # 1. form class 초기화(생성)
        form = CommentForm(instance=comment)

    context = {
        'form': form,
    }
    return render(request, 'articles/comments_edit.html', context)

 

이미지 업로드 하면 media 폴더에 저장되는 업로드 되는것을 볼 수 있음 

 

웹페이지 예시