[Django] DAY21. 백엔드 - 게시판 글쓰기 form 로직 구현

이하얀·2024년 2월 21일
0

2024년 2월 21일 수요일

📙 강의 내용 요약

  • 로그인이 필요한 서비스에 유저가 로그인되어 있는지 확인
# board/views.py
# 우선 제목과 내용만 받기

from django.shortcuts import render, redirect
from board.models import Post
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required

def board(request):
    # 게시글 리스트
    if request.method == "GET":
        page = request.GET.get('page', 1)
        search_text = request.GET.get('search_text', "")

        post_set = Post.objects.filter(
            title__icontains=search_text
            ).order_by('-id')
        paginator = Paginator(post_set, 2)

        post_set = paginator.get_page(page)

        context = {
            "post_set":post_set,
            "search_text":search_text,
        }
        return render(request, 'page/index.html', context=context)

@login_required(login_url="signin")
def post_write(request):
    if request.method=="GET":
        return render(request, "page/post_write.html")
    
    if request.method=="POST":
        title = request.POST["title"]
        content = request.POST["content"]

        Post(
            title=title,
            content=content,
        ).save()
        return redirect('board')
  • /post/write로 접근 시, 로그인 화면으로 이동
<!-- post_write.html -->
{% extends 'common/base.html' %}

{% block content %}
<div class="card">
    <div class="card-body text-end">
        <form method="post" enctype="multipart/form-data" id="write_form">
            {% csrf_token %}
            <input class="form-control my-2" type="text" name="title" placeholder="제목" id="title">
            <textarea
            id="content"
            style="height: 150px; resize: none;"
            class="form-control my-2"
            name="content"
            placeholder="한번 작성한 글은 삭제할 수 없습니다. 매너를 지켜주세요!"
            ></textarea>

            <input class="form-control" type="file" name="img" accept="image/*">

            <a class="text-decoration-none fs-5 my-2" id="write_btn"
            style="font-weight: bold;color: black;">글 작성</a>
        </form>
    </div>
</div>

<script>
    let title = document.getElementById("title");
    let content = document.getElementById("content");
    let write_btn = document.getElementById("write_btn");
    let write_form = document.getElementById("write_form");
    write_btn.addEventListener("click", ()=>{
        if(title.value === "" || content.value === ""){
            alert("내용을 작성해 주세요.");
        }else{
            write_form.submit()
        }
    });
</script>

{% endblock %}
# board/views.py

from django.shortcuts import render, redirect
from board.models import Post
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required

def board(request):
    # 게시글 리스트
    if request.method == "GET":
        page = request.GET.get('page', 1)
        search_text = request.GET.get('search_text', "")

        post_set = Post.objects.filter(
            title__icontains=search_text
            ).order_by('-id')
        paginator = Paginator(post_set, 2)

        post_set = paginator.get_page(page)

        context = {
            "post_set":post_set,
            "search_text":search_text,
        }
        return render(request, 'page/index.html', context=context)

@login_required(login_url="signin")
def post_write(request):
    if request.method=="GET":
        return render(request, "page/post_write.html")
    
    if request.method=="POST":
        title = request.POST["title"]
        content = request.POST["content"]

        Post(
            user=request.user,
            title=title,
            content=content,
        ).save()
        return redirect('board')


  • 이미지 업로드도 가능하도록 설정
    #anonymous.settings.py
    
    ...
    STATIC_URL = '/static/'
    
    # 이부분 작성
    MEDIA_ROOT = 'upload'
    ...
    # board/views.py
    
    from django.shortcuts import render, redirect
    from board.models import Post
    from django.core.paginator import Paginator
    from django.contrib.auth.decorators import login_required
    from django.core.files.storage import default_storage
    import uuid
    
    def board(request):
        # 게시글 리스트
        if request.method == "GET":
            page = request.GET.get('page', 1)
            search_text = request.GET.get('search_text', "")
    
            post_set = Post.objects.filter(
                title__icontains=search_text
                ).order_by('-id')
            paginator = Paginator(post_set, 2)
    
            post_set = paginator.get_page(page)
    
            context = {
                "post_set":post_set,
                "search_text":search_text,
            }
            return render(request, 'page/index.html', context=context)
    
    @login_required(login_url="signin")
    def post_write(request):
        if request.method=="GET":
            return render(request, "page/post_write.html")
        
        if request.method=="POST":
            title = request.POST["title"]
            content = request.POST["content"]
            img = request.FILES.get('img', None)
            img_url = ""
    
            if img:
                img_name = uuid.uuid4()
                ext = img.name.split('.')[-1]
    
                default_storage.save(f"{img_name}.{ext}", img)
                img_url = f"{img_name}.{ext}"
                #이미지 저장!
    
            Post(
                img_url=img_url,
                user=request.user,
                title=title,
                content=content,
            ).save()
            return redirect('board')


♻️ 느낀점&인사이트

오늘은 어제에 이어 게시판 글쓰기 form에 대한 백엔드 로직을 구현했다.

먼저, 제목과 내용에 해당하는 로직을 구성했는데, 사용자가 로그인되어 있지 않으면 글쓰기 페이지로 접근하더라도 로그인 페이지로 리다이렉팅될 수 있도록 했으며 로그인된 유저는 제목과 내용이 비어 있는 경우에만 글을 읽을 수 없도록 alert창을 띄워 막고 글을 업로드 할 수 있도록 했다.

그 다음, 이미지 파일 업로드에 해당하는 로직을 구현했다.

이미지의 경우 제목, 내용과는 다른 방식으로 작성되었기 때문에 ‘default storage’라는 다른 함수를 사용해야 했다.

이 함수를 사용하기 위해서는 django에서 약간의 설정을 해줘야 해서 설정부터 해줬다.

여기에서 주의할 점은, 다른 유저가 같은 제목을 글을 올릴 수 있다는 점이었기 때문에 유저를 구분하기 위해 img_name을 사용했다.

또한 확장자 역시 고려해야 하기 때문에 split으로 .을 기준으로 잘라내어 구현했다.

여기에서 한가지 고민했던 건 파일 확장자였다. 이미지도 png, jpg, jpeg 등 다양한데 모든 확장자를 잘 인식하고 저장할 수 있는지 여부가 가장 궁금했는데, 다행히 vscode와 github 모두에서 이미지가 잘 불러와졌다.

그리고 DBeaver에서도 post의 해당 글에 img_url이 잘 저장되어 있는 것까지 확인했다.

이렇게 글쓰기 로직에 대해서도 프론트엔드와 백엔드를 모두 완성했고, 앞으로의 강의 이름을 살펴보니 이제 게시판의 상세 페이지, 댓글까지의 기능이 남아있는 상태인 것 같다.

얼른 기능 개발을 마치고, 강의처럼 AWS를 이용하거나 비용 문제로 사용이 어렵다면 다른 무료 서비스를 이용해서라도 배포를 진행해보고 싶다는 생각이 많이 들었다!

profile
언젠가 내 코드로 세상에 기여할 수 있도록, BE&Data Science 개발 기록 노트☘️

0개의 댓글