해리의 데브로그

Django 14 - CRUD 구현 및 Django에 Bootstrap 입히기

|

1. 기본 설정

가상환경 및 기본설정

  • pyenv virtualenv 3.6.7 06_venv
  • pyenv local 06_venv
  • pip install django==2.1.8 : django 버전 설정
  • django-admin startproject insta .
  • python manage.py startapp posts
  • settings.pyINSTALLED_APPS & ALLOWED_HOSTS 설정
INSTALLED_APPS = [
    'posts',
    #'posts.apps.PostsConfig',]
ALLOWED_HOSTS = [] #기본값 입력

Model 설정

class Post(models.Model):
    content = models.TextField()
  • python manage.py makemigrations : 마이그레이션 초안 생성
  • python manage.py migrate : 설정된 스키마를 DB에 실제 적용

URL 경로 설정

  • 프로젝트 내 urls.py 설정
    • 어플리케이션 urls.py와 연결시키기 위해 include import 해옴
from django.urls import path, include

urlpatterns = [
    path('posts/', include('posts.urls')),]
  • 어플리케이션 내 urls.py 설정
    • views.py 내 함수 호출을 위해 import
    • 네임스페이스 posts 설정
from . import views

app_name = 'posts'

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

기본 템플릿 설정

  • 프로젝트 폴더 / templates 폴더 / base.html
  • CDN 설정하기 (Bootstrap - CSS & JSS, fontawesome)
<body>
    {% block container %}
    {% endblock %}
</body>
</html>
  • Settings.py 내 기본 템플릿 경로 설정
'DIRS': [os.path.join(BASE_DIR, 'insta', 'templates')],

모델 폼 작성

  • 어플리케이션 폴더 내 forms.py 파일 생성
  • 장고 내 forms 및 모델 클래스 Post를 import 해옴
  • model에는 연동하고자 하는 모델 클래스를 저장
from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['content']

MTV에 따라 Create 기능 구현

  • urls.py 내 url 경로 설정
  • views. py 내 가장 기본적인 템플릿으로 create 함수 생성
  • 앱 폴더 내 templates 폴더 생성 후, create.html 생성.
    • 기본적인 form 태그 양식에 따라 코드 작성


2. Django에 Bootstrap 입히기

django-bootstrap4 설치

  • pip install django-bootstrap4 : 외부 라이브러리 설치
  • settings.py 내 INSTALLED_APPS 내에 앱 추가
INSTALLED_APPS = [
    'bootstrap4',
]

base.html 수정

  • bootstrap 관련 CDN 코드 삽입
<head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>

create.html 수정

  • {% load bootstrap4 %} 을 템플릿 상속을 위한 코드 사이에 넣어줘야 함.
  • {% bootstrap_form 템플릿 변수 %} : 부트스트랩을 적용한 템플릿 변수 양식
    • cf) {{ 템플릿 변수 }} : 기본 방식
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block container %}
<h1>New Post</h1>

<form method="post">
    {% csrf_token %}
     <!-- 기본방식 {{ post_form }}-->
     <!-- 부트스트랩 클래스 이용 -->
    {% bootstrap_form post_form %}
    <input type="submit" value="Submit"/>
</form>
{% endblock %}
  • 버튼 모양 수정
{% buttons %}
<button type="submit" class="btn btn-primary">Submit</button>
{% endbuttons %}

3. CRUD & Model Form 적용

1) Create 페이지 수정

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

def create(request):
    #POST 방식일 경우
    if request.method == 'POST':
        post_form = PostForm(request.POST)
        
        #모델 폼이 유효 할 경우
        if post_form.is_valid():
            post_form.save()
            return redirect('posts:list')
    
    #Get 방식일 경우
    else:
        post_form = PostForm()
    return render(request, 'posts/create.html', {'post_form': post_form})

2) list페이지 작성

  • views.py
from .models import Post

def list(request):
    posts = Post.objects.all()
    return render(request, 'posts/list.html'. {'posts':posts})
  • list.html
    • 세부 내용은 _post.html에 작성
    • {% include 'posts/_post.html' %}
{% extends 'base.html' %}
{% block container %}

<h1> Post List </h1>

<!-- 진자 템플릿 사용 -->
{% for post in posts %}
<!-- 세부 내용은 _post.html에 작성 -->
{% include 'posts/_post.html' %}

{% endfor %}
{% endblock %}
  • _post.html
    • 재사용성을 위해 파일을 분리시킴
    • 파일의 제목은 반드시 _ 로 시작할 필요는 없으나, _를 사용하는 것이 통상적인 룰.
    • 어플리케이션 폴더 - 템플릿 폴더 내 _post.html 파일 생성 후 코드 작성
    • bootstrap - card를 사용
<div class="card" style="width: 18rem;">
  <img src="..." class="card-img-top" alt="...">
  <div class="card-body">
    <p class="card-text"></p>
  </div>
</div>

3) Delete

  • urls.py
from django.urls import path
from . import views

app_name = 'posts'

urlpatterns = [
    path('<int:post_id>/delete/', views.delete, name='delete'),
]
  • views.py
def delete(request, post_id):
    #기본키를 뜻하는 pk=post_id를 써도 되고, 아니면 id를 써도됨. 
    post = Post.objects.get(id=post_id)
    post.delete()
    
    return redirect('posts:list')
  • _post.html
<div class="card" style="width: 18rem;">
    <!-- 장고 템플릿 문법을 사용하여 삭제하는 링크 설정 -->
    <a href="{% url 'posts:delete' post.id %}" class="btn btn-primary">Delete</a>
  </div>
</div>
  • get_object_or_404
    • url 주소로 이미 삭제 된 id를 이용하려는 접근할 경우 에러가 발생함.
    • 존재 하지 않는 id 값 기반의 url 주소로 접속할 경우, 에러가 발생하므로 Movie.objects.get 대신 get_object_or_404 를 사용하여 404 에러 메세지(Page not found)를 표시하게 코드 작성(사용자 친화적)
    • 사용을 위해 import 해올 것. from django.shortcuts import get_object_or_404
from django.shortcuts import render, redirect, get_object_or_404

def delete(request, post_id):
    # post = Post.objects.get(id=post_id)
    post = get_object_or_404(Post, id=post_id)
    post.delete()
    return redirect('posts:list')

4) update

  • urls.py
urlpatterns = [
    path('<int:post_id>/like/', views.like, name='like'),
]
  • views.py
    • create.html 을 그대로 사용
def update(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    
    if request.method == 'POST':
        postform = Postform(request.POST, instance=post)
        if postform.is_valid():
            postform.save()
            return redirect('posts:detail', post_id)
    
    else:
        postform = Postform(instance=post)
        return render(request, 'posts/create.html', {'postform':postform})
  • _post.html
    • 장고 템플릿 사용하여 수정 링크 추가
<a href="{% url 'posts:update' post.id %}" class="btn btn-info">Update</a>

Comments