[DjangoCRUD] 장고 CRUD 활용하기


장고 CRUD 활용하기

Create, Read, Update, Delete


crud - urls.py 코드 수정

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

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

boards - urls.py 생성 후 코드 수정

from django.urls import path
from . import views

# 이름은 반드시 urlpatterns 라고 해야 장고가 자동으로 경로를 찾는다!!
urlpatterns = [
    path('', views.index),  # '' 는 boards라고 생각하면 된다.
    path('new/', views.new),  # 사용자 입력 페이지
    path('create/', views.create),  # 데이터 저장 페이지
]

boards - views.py 코드 수정

from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, 'boards/index.html')

boards 안에 templates 폴더 만들기

boards - templates 폴더 안에 boards 폴더 만들기

boards - templates - boards 폴더 안에 index.html 파일 생성 후 코드 작성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>boards - index</title>
</head>
<body>

    <h1>Welcome to Boards page</h1>

</body>
</html>

사용자가 입력하는 페이지 : new.html

boards - templates - boards - new.html 코드 작성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>boards - new</title>
</head>
<body>

    <h1>NEW</h1>
    <form action="">
        <input type="text", name="title" />
        <textarea name="content" id="" cols="30" rows="10"></textarea>
        <input type="submit">
    </form>

</body>
</html>

UPDATE


boards - urls.py 생성 후 코드 수정

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index),  # www.web.com/boards/
    path('new/', views.new),  # 사용자의 입력을 받아서 게시글을 작성하는 곳
    path('create/', views.create),  # 사용자가 입력한 데이터를 전송받고 실제 DB에 작성 및 사용자 피드백
    path('<int:id>/', views.detail),  # www.web.com/boards/<id>/
    path('<int:id>/delete/', views.delete),
    path('<int:id>/edit/', views.edit),  # 게시글 수정 페이지 렌더링
]

boards - views.py 코드 수정

from django.shortcuts import render, redirect
from .models import Board

# Create your views here
def index(request):
    # Board 의 전체 데이터를 불러온다 - QuerySet
    boards = Board.objects.all()
    context = {'boards': boards}
    return render(request, 'boards/index.html', context)

# 사용자 입력을 받는 페이지 렌더링
def new(request):
    return render(request, 'boards/new.html')

# 데이터를 받아서 실제 DB 에 작성
def create(request):
    title = request.POST.get('title')
    content = request.POST.get('content')
    board = Board(title=title, content=content)
    board.save()
    return redirect(f'/boards/{board.id}/')

# 특정 게시글 하나만 가지고 온다.
def detail(request, id):
    # Board 클래스를 사용해서 id 값에 맞는 데이터를 가지고 온다.
    # context 로 넘겨서 detail.html 페이지에서 title 과 content 를
    # 출력해본다.
    board = Board.objects.get(id=id)
    context = {'board': board}
    return render(request, 'boards/detail.html', context)

def delete(request, id):
    board = Board.objects.get(id=id)
    board.delete()
    return redirect('/boards/')

# 게시글 수정 페이지 렌더링
def edit(request):
    return render(request, 'boards/edit.html')

사용자가 수정하는 페이지 : edit.html

boards - templates - boards - edit.html 코드 작성


{% extends 'boards/base.html' %}

{% block body %}
    <h1>EDIT</h1>
    <form action="/boards/create/" method="post">
        {% csrf_token %}
        <label for="title">Title</label><br />
        <input name="title" id="title" type="text" value="{{ board.title }}"/><br />  <!-- value="{{ board.title }} : 기존에 작성한거 보여줌 -->
        <label for="content">Content</label><br />
        <textarea name="content" id="content">{{ board.content }}</textarea><br />
        <input type="submit" />
    </form>
    <a href="/boards/">BACK</a>
{% endblock %}

수정하고 저장하는 함수 및 패스 등등 : update

boards - urls.py 코드 수정

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index),  # www.web.com/boards/
    path('new/', views.new),  # 사용자의 입력을 받아서 게시글을 작성하는 곳
    path('create/', views.create),  # 사용자가 입력한 데이터를 전송받고 실제 DB에 작성 및 사용자 피드백
    path('<int:id>/', views.detail),  # www.web.com/boards/<id>/
    path('<int:id>/delete/', views.delete),
    path('<int:id>/edit/', views.edit),  # 게시글 수정 페이지 렌더링
    path('<int:id>/update/', views.update),  # 사용자가 입력한 수정 데이터를 전송 받고 실제 DB 에 수정 후 저장
]

boards - views.py 코드 수정

from django.shortcuts import render, redirect
from .models import Board


# Create your views here
def index(request):
    # Board 의 전체 데이터를 불러온다 - QuerySet
    boards = Board.objects.all()
    context = {'boards': boards}
    return render(request, 'boards/index.html', context)


# 사용자 입력을 받는 페이지 렌더링
def new(request):
    return render(request, 'boards/new.html')


# 데이터를 받아서 실제 DB 에 작성
def create(request):
    title = request.POST.get('title')   # 사용자가 POST로 보낸 걸 get 가져오기
    content = request.POST.get('content')   # 사용자가 POST로 보낸 걸 get 가져오기
    board = Board(title=title, content=content)
    board.save()
    return redirect(f'/boards/{board.id}/')


# 특정 게시글 하나만 가지고 온다.
def detail(request, id):
    # Board 클래스를 사용해서 id 값에 맞는 데이터를 가지고 온다.
    # context 로 넘겨서 detail.html 페이지에서 title 과 content 를
    # 출력해본다.
    board = Board.objects.get(id=id)
    context = {'board': board}
    return render(request, 'boards/detail.html', context)


def delete(request, id):
    board = Board.objects.get(id=id)
    board.delete()
    return redirect('/boards/')


# 게시글 수정 페이지 렌더링
def edit(request, id):
    # id 값에 맞는 board 데이터 꺼낸 후 edit.html 로 넘기기
    board = Board.objects.get(id=id)
    context = {'board': board}
    return render(request, 'boards/edit.html', context)


def update(request, id):
    title = request.POST.get('title')   # 사용자가 POST 로 보낸 걸 get 가져오기
    content = request.POST.get('content')   # 사용자가 POST 로 보낸 걸 get 가져오기
    # id 값에 맞는 board 데이터를 위에서 주어진 title 과 content 에 맞게 수정한 뒤 저장하는 로직
    # 1. Board 클래스를 통해 id 값에 맞는 데이터를 가져온다.
    board = Board.objects.get(id=id)
    # 2. 해당 데이터의 내용을 주어진 title, content 로 수정한다.
    board.title = title
    board.content = content
    # 3. 저장한다.
    board.save()

    # print(title, content)
    return redirect(f'/boards/{id}/')

boards - templates - boards - edit.html 코드 수정


{% extends 'boards/base.html' %}

{% block body %}
    <h1>EDIT</h1>
    <form action="/boards/{{ board.id }}/update/" method="post">
        {% csrf_token %}
        <label for="title">Title</label><br />
        <input name="title" id="title" type="text" value="{{ board.title }}"/><br />  <!-- value="{{ board.title }} : 기존에 작성한거 보여줌 -->
        <label for="content">Content</label><br />
        <textarea name="content" id="content">{{ board.content }}</textarea><br />
        <input type="submit" />
    </form>
    <a href="/boards/">BACK</a>
{% endblock %}


boards - templates - boards - detail.html 코드 수정


{% extends 'boards/base.html' %}

{% block body %}
    <h1>Detail</h1>
    <h2>{{ board.title }}</h2>
    <p>{{ board.id }}번째 </p>
    <p>{{ board.created_at }}</p>
    <hr />
    <p>{{ board.content }}</p>
    <hr />
    <a href="/boards/">[뒤로가기]</a>
    <form action="/boards/{{ board.id }}/delete/" method="post">
        {% csrf_token %}
        <input class="btn btn-danger" type="submit" value="삭제하기"/>
    </form>

    <a href="/boards/{{ board.id }}/edit/">[수정하기]</a>

{% endblock %}

게시판 완성!!


TIP


ex) /board/를 /board//detail로 바꾸고자 할때 어떻게 하면 좋을까요?

boards - urls.py 코드 수정

  • 세번째 인자를 줄 수도 있다.
  • 추가로 변수 설정
from django.urls import path
from . import views


app_name = 'boards'


urlpatterns = [
    path('', views.index, name='index'),  # www.web.com/boards/
    path('new/', views.new, name='new'),  # 사용자의 입력을 받아서 게시글을 작성하는 곳
    path('create/', views.create, name='create'),  # 사용자가 입력한 데이터를 전송받고 실제 DB에 작성 및 사용자 피드백
    path('<int:id>/', views.detail, name='detail'),  # www.web.com/boards/<id>/
    path('<int:id>/delete/', views.delete, name='delete'),
    path('<int:id>/edit/', views.edit, name='edit'),  # 게시글 수정 페이지 렌더링
    path('<int:id>/update/', views.update, name='update'),  # 사용자가 입력한 수정 데이터를 전송 받고 실제 DB 에 수정 후 저장
]

boards - views.py 코드 수정

(기존) return redirect(f'/boards/{id}/')
(변경) return redirect('boards:detail', id)    # boards:detail 콜론에 띄어쓰기가 있으면 안됨.

from django.shortcuts import render, redirect
from .models import Board


# Create your views here
def index(request):
    # Board 의 전체 데이터를 불러온다 - QuerySet
    boards = Board.objects.all()
    context = {'boards': boards}
    return render(request, 'boards/index.html', context)


# 사용자 입력을 받는 페이지 렌더링
def new(request):
    return render(request, 'boards/new.html')


# 데이터를 받아서 실제 DB 에 작성
def create(request):
    title = request.POST.get('title')   # 사용자가 POST로 보낸 걸 get 가져오기
    content = request.POST.get('content')   # 사용자가 POST로 보낸 걸 get 가져오기
    board = Board(title=title, content=content)
    board.save()
    # return redirect(f'/boards/{board.id}/')
    return redirect('boards:detail', board.id)

# 특정 게시글 하나만 가지고 온다.
def detail(request, id):
    # Board 클래스를 사용해서 id 값에 맞는 데이터를 가지고 온다.
    # context 로 넘겨서 detail.html 페이지에서 title 과 content 를
    # 출력해본다.
    board = Board.objects.get(id=id)
    context = {'board': board}
    return render(request, 'boards/detail.html', context)


def delete(request, id):
    board = Board.objects.get(id=id)
    board.delete()
    # return redirect('/boards/')
    return redirect('boards:index')  # boards:index 콜론에 띄어쓰기가 있으면 안됨.


# 게시글 수정 페이지 렌더링
def edit(request, id):
    # id 값에 맞는 board 데이터 꺼낸 후 edit.html 로 넘기기
    board = Board.objects.get(id=id)
    context = {'board': board}
    return render(request, 'boards/edit.html', context)


def update(request, id):
    title = request.POST.get('title')   # 사용자가 POST 로 보낸 걸 get 가져오기
    content = request.POST.get('content')   # 사용자가 POST 로 보낸 걸 get 가져오기
    # id 값에 맞는 board 데이터를 위에서 주어진 title 과 content 에 맞게 수정한 뒤 저장하는 로직
    # 1. Board 클래스를 통해 id 값에 맞는 데이터를 가져온다.
    board = Board.objects.get(id=id)
    # 2. 해당 데이터의 내용을 주어진 title, content 로 수정한다.
    board.title = title
    board.content = content
    # 3. 저장한다.
    board.save()

    # print(title, content)
    # return redirect(f'/boards/{id}/')
    return redirect('boards:detail', id)  # boards:detail 콜론에 띄어쓰기가 있으면 안됨.


boards - templates - boards - index.html 코드 수정


{% extends 'boards/base.html' %}

{% block body %}
    <h1>Welcome to boards</h1>
    <hr />
    {% for board in boards %}
        <p> 번호 : [{{ board.id }}]ㅤㅤ ㅤㅤ ㅤㅤ  제목 : {{ board.title }}ㅤㅤㅤ  ㅤㅤ  내용 : {{ board.content }} </p>
        <!--<a href="/boards/{{ board.id }}/">[상세글 보러가기]</a>-->
        <a href="{% url 'boards:detail' board.id %}">[상세글 보러가기]</a>
        <hr />
    {% endfor %}

boards - templates - boards - new.html 코드 수정


{% extends 'boards/base.html' %}

{% block body %}
    <h1>NEW</h1>
    <!--<form action="/boards/create/" method="post">-->
    <form action="{% url 'boards:create' %}" method="post">
        {% csrf_token %}
        <label for="title">Title</label><br />
        <input name="title" id="title" type="text" /><br />
        <label for="content">Content</label><br />
        <textarea name="content" id="content"></textarea><br />
        <input type="submit" />
    </form>
    <!--<a href="/boards/">BACK</a>-->
    <a href="{% url 'boards:index' %}">BACK</a>
{% endblock %}

boards - templates - boards - edit.html 코드 수정


{% extends 'boards/base.html' %}

{% block body %}
    <h1>EDIT</h1>
    <!--<form action="/boards/{{ board.id }}/update/" method="post">-->
    <form action="{% url 'boards:update' board.id %}" method="post">
        {% csrf_token %}
        <label for="title">Title</label><br />
        <input name="title" id="title" type="text" value="{{ board.title }}"/><br />  <!-- value="{{ board.title }} : 기존에 작성한거 보여줌 -->
        <label for="content">Content</label><br />
        <textarea name="content" id="content">{{ board.content }}</textarea><br />
        <input class="btn btn-success" type="submit" value="제출하기" />
    </form>

    <!--<a href="/boards/">[뒤로가기]</a>-->
    <!--<form action="/boards/" method="post">-->
    <form action="{% url 'boards:index' %}" method="post">
        {% csrf_token %}    <!-- 우리 웹 서버에서 어떤 작성이 일어날때는 csrf_token이 필요하다라는 의미 // 보안상 필요 -->
        <input class="btn btn-secondary" type="submit" value="뒤로가기"/>
    </form>
{% endblock %}

boards - templates - boards - detail.html 코드 수정


{% extends 'boards/base.html' %}

{% block body %}
    <h1>EDIT</h1>
    <!--<form action="/boards/{{ board.id }}/update/" method="post">-->
    <form action="{% url 'boards:update' board.id %}" method="post">
        {% csrf_token %}
        <label for="title">Title</label><br />
        <input name="title" id="title" type="text" value="{{ board.title }}"/><br />  <!-- value="{{ board.title }} : 기존에 작성한거 보여줌 -->
        <label for="content">Content</label><br />
        <textarea name="content" id="content">{{ board.content }}</textarea><br />
        <input class="btn btn-success" type="submit" value="제출하기" />
    </form>

    <!--<a href="/boards/">[뒤로가기]</a>-->
    <!--<form action="/boards/" method="post">-->
    <form action="{% url 'boards:index' %}" method="post">
        {% csrf_token %}    <!-- 우리 웹 서버에서 어떤 작성이 일어날때는 csrf_token이 필요하다라는 의미 // 보안상 필요 -->
        <input class="btn btn-secondary" type="submit" value="뒤로가기"/>
    </form>
{% endblock %}

ADMIN 계정 만들기


터미널 실행 python manage.py createsuperuser

(venv)   DjangoCRUD git:(master) python manage.py createsuperuser
사용자 이름: kangpro
이메일 주소: 
Password: kangpro@
Password (again): kangpro@
비밀번호가 사용자 이름와 너무 유사합니다.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
(venv)   DjangoCRUD git:(master) 

boards - admin.py 수정

from django.contrib import admin
from .models import Board


# Register your models here.
# admin 페이지에 board 추가
admin.site.register(Board)

boards - models.py 수정

from django.db import models


# Create your models here.
# 상속
# 상속 받고자하는 다른 class 를 ()괄호 안에 넣어준다.
class Board(models.Model):

    # 클래스 변수 -> DB 의 필드를 나타냄.
    # id 는 기본적으로 처음 테이블 생성시 자동으로 만들어진다. 그래서 아래와 같이 만들어도 되고 안 만들어도 된다.
    # id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=20)  # 길이의 문자열을 제한할 때 쓴다.  # CharField 괄호 안에 max_length=0 가 필수로 있어야 한다.
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)  # auto_now_add : '객체를 하나 생성할 때만 시간을 담겠다' 라는 의미
    updated_at = models.DateTimeField(auto_now=True)  # auto_now : 지금 작업을 할 때


    # 인스턴스 그 자체 형식을 어떻게 출력할지 정하는 class method 다
    def __str__(self):
        return f'{self.id}번째 글ㅤㅤ ㅤㅤ ㅤㅤ {self.title} : {self.content}'


환경


macOS Mojave 10.14.5, python 3.6.8, django 2.2.1, PyCharm CE 2018.3.7.






© 2020. GANGPRO. All rights reserved.