ACHO.pk devlog

[멋쟁이사저처럼10기] Django 개발자 대나무숲 프로젝트(익명 게시판) 본문

멋쟁이사자처럼

[멋쟁이사저처럼10기] Django 개발자 대나무숲 프로젝트(익명 게시판)

Acho 2022. 7. 8. 21:37

migrate, migration 명령어는 정말 꼭 해야한다.

'no such table'이라는 에러가 계속 뜨길래 무슨 문제인 지 생각했는데, 역시나 migrate을 안 했던 것이다.... 꼭 하자!


먼저, bootstrap 템플릿을 고르면 된다.

https://startbootstrap.com/

 

Free Bootstrap Themes, Templates, Snippets, and Guides - Start Bootstrap

Landing Page A clean, functional landing page theme

startbootstrap.com

 

<초기설정>

1. 프로젝트 생성_myproject

2. 어플리케이션 생성_snsapp + 어플리케이션 등록

3. 베이스 폴더 하위에 static 폴더 생성 + static 경로 설정(settings.py)

4. static 폴더에 bootstrap template css, js... 등 넣기

5. 어플리케이션 폴더 하위에 'templates' 폴더 생성 + bootstrap template html 넣기

6. views.py에 index.html을 요청하는 함수 생성

from django.shortcuts import render

def home(request):
    return render(request, 'index.html')

7.base.html로 공통되는 부분 정리

여기서 중요한 것은 template 언어를 써줘야한다는 점이다...

공통되는 부분

{% block content %}
	<!-- 이 부분은 각각의 html에서.. -->
{% endblock %}

공통되는 부분

8. 공통되는 부분 정리 후 각각의 html에

{% block content %}

<!-- 공통되지 않은 부분 코드 쓰기 -->

{% endblock %}

 

 

models.py > forms.py > views.py 순으로 이해하면 쉽다.


익명게시판 구현하기

 

snsapp/models.py

우리가 만들고자 하는 table로 삼고자하는 모델을 정해준다.

from django.db import models

#게시물 모델
class Post(models.Model):
    title = models.CharField(max_length = 200)
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)  #객체가 추가될 때의 시간을 date에 넣을 수 있음
    
    def __str__(self): #게시글 제목
        return self.title

게시글의 제목, 본문, 날짜에 해당하는 칼럼을 만들어준다.

 

변경사항이 담긴 파일을 생성해준 후,

python manage.py makemigrations

데이터베이스에 반영한다.

python manage.py migrate

 

snsapp/admin.py

게시물 model은 django admin 사이트에서도 확인할 수 있기 때문에 Post를 등록해준다.

from django.contrib import admin
from .models import Post

admin.site.register(Post)

 

admin 계정 생성

 python manage.py createsuperuser

 다운받은 bootstrap 템플릿에 table.html 이 있다. 그 파일에서 필요한 부분만 복사해 index.html(랜딩 페이지)에 붙여넣기를 하면 된다.


글쓰기 버튼 생성 + 제출

다운 받은 bootstrap 템플릿을 보면 Components에 우리가 사용할 수 있는 buttons이 있다. buttons.html에서 원하는 버튼에 해당하는 코드를 복사해서 index.html 파일에 붙여넣기를 하면 된다.

 index.html

<!--로그인 성공했을 시에 글쓰기 버튼 생성-->
{% if user.is_authenticated %}
<a href="{% url 'postcreate' %}" class="btn btn-success btn-icon-split">
    <span class="icon text-white-50">
        <i class="fas fa-flag"></i>
    </span>
    <span class="text">글쓰기</span>
</a>
{% endif %}

 

urls.py

urlpatterns = [
	path('postcreate', views.postcreate, name='postcreate'),
]

 

forms.py

입력값을 받아들이기 위해 forms.py 생성한다.

from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        super(PostForm, self).__init__(*args, **kwargs)

        self.fields['title'].widget.attrs = {
            'class': 'form-control',
            'placeholder': "글 제목을 입력해주세요",
            'rows': 20
        }

        self.fields['body'].widget.attrs = {
            'class': 'form-control',
            'placeholder': "글 제목을 입력해주세요",
            'rows': 20,
            'cols' : 100
        }

 

views.py

from django.shortcuts import render, redirect
from .forms import PostForm
from .models import Post

def postcreate(request):
    # request method가 POST 일 경우
    if request.method == 'POST' or request.method == 'FILES':
        form = PostForm(request.POST, request.FILES)
        # 입력값 저장
        if form.is_valid():
            form.save()
            return redirect('home')
    # request method가 GET 일 경우
    else:
        form = PostForm()
    # form 입력 html 띄우기
    return render(request, 'post_form.html', {'form':form})

 

post_form.html ( 글 작성 + 제출 )

{% extends 'base.html' %}
{% block content %}

<!-- 제출 버튼을 눌렀을 때 HTTP POST 요청 -->
<form action="" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <table>
        {{form.as_p}}
    </table>
    <br/>
    <input type="submit" class="btn btn-success btn-icon-split btn-sm" value="create">
</form>
{% endblock %}

 


상세 페이지 제작

 

models.py

from .models import Post

def home(request):
    # posts = Post.objects.all()
    
    posts = Post.objects.filter().order_by('-date')
    return render(request, 'index.html', {'posts':posts})

 

index.html

  • template 언어로 for문을 사용해서 posts라고 하는 Query Set 객체에 있는 것들을 순회해서 post에 담아준다.
  • {{ post }} 만 하면 QuerySet 자체가 뜨게 되므로, 순회하는 과정이 필요한 것이다. ( 크롤링과 비슷 )

 

  • 그리고 게시글 제목을 클릭하면 해당 글의 페이지로 넘어갈 수 있다. ( 상세 페이지 이동)
  • 따라서 글 제목에 링크를 달아줘야한다. 
  • 또한, post.id detail 이라고 하는 url로 이동을 한다.
{% extends 'base.html' %}
{% block content %}

<div class="card shadow mb-4">
    <div class="card-header py-3">
        <h6 class="m-0 font-weight-bold text-success">익명게시판</h6>
    </div>
    <div class="card-body">
        <div class="table-responsive">
            <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
                <thead>
                    <tr>
                        <th width='70%'>글 제목</th>
                        <th>작성 날짜</th>
                        <th>작성자</th>
                    </tr>
                </thead>
                <tbody>
                    {% for post in posts %}
                    <tr>
                        <td><a href="{% url 'detail' post.id %}">{{ post.title }}</a></td>
                        <td>{{ post.date }}</td>
                        <td>익명</td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>

{% endblock %}

 

myproject/urls.py

  • http://127.0.0.1:8000/detail/1
  • http://127.0.0.1:8000/detail/2
  • http://127.0.0.1:8000/detqil/3

와 같은 url을 생성하기 위해 <int:post_id> 인자를 적어준다.

urlpatterns = [ 
 path('detail/<int:post_id>', views.detail, name='detail'),
 ]

 

snsapp/views.py

  • get_object_or_404 : Post 객체를 갖고오거나 pk 값은 인자로 전달받은 post_id(index.html에서 옴)를 받아온다.
  • index.html에서의 'detail'과 post.id 값이 urls.py로 전달되고, 2번째 인자로서 detail이라는 함수로 인자가 views.py로 전달이 되고, 전달을 받은 post_id로서 특정 pk 값을 갖고 있는 Post 객체를 가져오는 것이다.(게시글을 가져옴)
  • 'post_detail'에 해당하는 post_detail 데이터를 보여줄 detail.html를 생성해야 한다. 후자 데이터도 마찬가지..
from django.shortcuts import render, redirect, get_object_or_404
from .models import Post

def detail(request, post_id):
    post_detail = get_object_or_404(Post, pk=post_id)
    return render(request, 'detail.html', {'post_detail':post_detail})

 

 

detail.html

{% extends 'base.html' %}

{% block content %}

<h1>제목: {{ post_detail.title }}</h1>
<h2>작성날짜: {{ post_detail.date}}</h2>
<p>
    {{ post_detail.body }}
</p>

{% endblock %}

게시글 제목 클릭 시 상세 페이지로 이동

 

 

 

Comments