티스토리 뷰

INTRO

0. Test 용 template 만들기 : bootstrap 활용

1. model 생성 및 migration : django 관리자를 이용한 CRUD control

2. view 만들기

 

3. template 적용하기

4. model-form을 이용한 CRUD Control
    Create : 생성, New(model-form + POST method)
    Read : 조회, Detail
    Update : 수정(model-form + Post method)
    Delete : 삭제

 

들어가기 전에 사전 이해가 필요한 사항

- django 가상환경 및 프로젝트 생성/설정 : 참고1, 참고2

- app 생성과 template 및 static/css 기초 : 참고

- bootstrap 적용 및 template 분리(base/sidebar/topbar/footer) : 참고1, 참고2 

 

0. Test 용 template 만들기

web-site에서 기본으로 구성되는 template를 구성해본다.
django의 back-end test를 위해 front-end에 해당하는 html, css, javascript 접근이 용이한 bootstrap을 이용

step1. bootstrap sbadmin2 theme 다운 : https://startbootstrap.com/theme/sb-admin-2

step2. css/style.css와 js/datatables-simple-demo.js를 django project의 static/css, static/js에 각각 복사

step3. board app을 생성하고 board/templates/board/test_index.html을 생성

board/templates/board/test_index.html
{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <title>{% block title %}{{ section.title }}{% endblock %}</title>
        <link href="{% static 'css/styles.css' %}" rel="stylesheet" />
    </head>

    <body class="sb-nav-fixed">
        <div id="layoutSidenav">
            <!-- Topbar -->
            <nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
                <!-- Navbar Brand-->
                <a class="navbar-brand ps-3" href="{% url 'board:test_index' %}" style="color:lightgray; font-size:1.7em">App_Test</a>
                <!-- Navbar Top-->
                <div style="color:darkgray; font-size:2em">Test_title</div>
            </nav>
            <!-- Sidebar -->
            <div id="layoutSidenav_nav">
                <nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
                    <div class="sb-sidenav-menu">
                        <div class="nav">
                            <a class="nav-link" href="#">
                                hyperlink 1
                            </a>
                            <a class="nav-link" href="#">
                                hyperlink 2
                            </a>
                        </div>
                    </div>
                </nav>
            </div>

            <!-- Main_Contents -->
            <div id="layoutSidenav_content">
                <main>
                    <div class="container-fluid px-4">
                        <!-- Main_content_#1 -->
                        <h3 class="mt-4">QuerySet View</h3>
                        <div class="card mb-4">
                            <div class="card-header">
                                QuerySet Board | <a href="#">글쓰기</a>
                            </div>
                            <div class="card-body">
                                <p>{{ orms template tag part }}</p>
                            </div>
                        </div>

                        <!-- Main_content_#2 -->
                        <h3 class="mt-4">Form View</h3>
                        <div class="card mb-4">
                            <div class="card-header">
                                Form Board | <a href="#">글쓰기</a>
                            </div>
                            <div class="card-body">
                                <p>{{ forms template tag part }}</p>
                            </div>
                        </div>

                        <!-- Main_content_#3 -->
                        <h3 class="mt-4">Table View</h3>
                        <div class="card mb-4">
                            <div class="card-header">
                                <i class="fas fa-table me-1"></i>
                                Table Board | <a href="#">글쓰기</a>
                            </div>
                            <div class="card-body">
                                <table id="datatablesSimple">
                                    <thead>
                                        <tr>
                                            <th>순번</th>
                                            <th>제목</th>
                                            <th>작성자</th>
                                            <th>내용</th>
                                            <th>날짜</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                    {% for orm in orms %}
                                        <tr>
                                            <td>{{ orm.field0 }}</td>
                                            <td>{{ orm.field1 }}</td>
                                            <td>{{ orm.field2 }}</td>
                                            <td>{{ orm.field3 }}</td>
                                            <td>{{ orm.field4 | date:'Y-m-d' }}</td>
                                        </tr>
                                    {% endfor %}
                                    </tbody>
                                </table>
                            </div>
                        </div>

                        <!-- Main_content_#4 -->

                    </div>
                </main>
            </div>
        </div>
        <!-- Table js source -->
        <script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest" crossorigin="anonymous"></script>
        <script src="{% static 'js/datatables-simple-demo.js' %}"></script>
    </body>
</html>

 

step4. config/urls.py, board/urls.py, board/views.py를 개발서버에 띄운다.

config/urls.py
from django.contrib import admin
from django.urls import path, include
from board import urls


urlpatterns = [
    path('admin/', admin.site.urls),
    path('board/', include('board.urls')),
]
board/urls.py
from django.urls import path
from . import views

app_name = 'board'

urlpatterns = [
    path('test_index/', views.test_index, name='test_index'),
]
board/views.py
from django.shortcuts import render

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

 

browser : localhost:8000/board/test_index/

 

 

 

1. model 생성 및 migration 

model 생성
DB migration, migrate
admin control : django 관리자 admin을 이용하여 CRUD 기본 형태 이해

 

board/models.py
from django.db import models

# Create your models here.
class BoardTest(models.Model):
	title   = models.CharField(db_column='title', max_length=200)
	author  = models.CharField(db_column='author', max_length=30)
	article = models.TextField(db_column='article', null=True)
	date    = models.DateTimeField(auto_now_add=True)
	
	def __str__(self):
		return self.title

$ ./manage.py makemigrations board

$ ./manage.py migrate

board/admin.py
from django.contrib import admin
from board.models import BoardTest


# Register your models here.
class BoardTestAdmin(admin.ModelAdmin):
	search_fields = ['title']

admin.site.register(BoardTest, BoardTestAdmin)

 

admin에 접속하여 BOARD TEST 추가를 이용하여 CRUD(생성/읽기/수정/삭제) 사용해보기
board/views.py의 template rendering을 위해 boardtest에 record 4개를 생성한다

 

browser : localhost:8000/admin/board/boardtest/

 

2. view 만들기

views.py
from django.shortcuts import render

from .models import BoardTest
from .forms import BoardTestForm


# Create your views here.
def test_index(request):
	boards = BoardTest.objects.all()
	forms  = BoardTestForm()
	ctx = {'boards':boards, 'forms':forms}
	return render(request, 'board/test_index.html', ctx)

 

 

3. template 적용하기

{{ template tag part }} 부분을 수정하여 django 관리자에서 작성한 ORM의 QuerySet, Form, Table View 적용
board/templates/board/test_index.html
{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <title>{% block title %}{{ section.title }}{% endblock %}</title>
        <link href="{% static 'css/styles.css' %}" rel="stylesheet" />
    </head>

    <body class="sb-nav-fixed">
        <div id="layoutSidenav">
            <!-- Topbar -->
            <nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
                <!-- Navbar Brand-->
                <a class="navbar-brand ps-3" href="{% url 'board:test_index' %}" style="color:lightgray; font-size:1.7em">App_Test</a>
                <!-- Navbar Top-->
                <div style="color:darkgray; font-size:2em">Test_title</div>
            </nav>
            <!-- Sidebar -->
            <div id="layoutSidenav_nav">
                <nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
                    <div class="sb-sidenav-menu">
                        <div class="nav">
                            <a class="nav-link" href="#">
                                hyperlink 1
                            </a>
                            <a class="nav-link" href="#">
                                hyperlink 2
                            </a>
                        </div>
                    </div>
                </nav>
            </div>

            <!-- Main_Contents -->
            <div id="layoutSidenav_content">
                <main>
                    <div class="container-fluid px-4">
                        <!-- Main_content_#1 -->
                        <h3 class="mt-4">QuerySet View</h3>
                        <div class="card mb-4">
                            <div class="card-header">
                                QuerySet Board | <a href="#">글쓰기</a>
                            </div>
                            <div class="card-body">
                                <p>{{ boards }}</p>
                            </div>
                        </div>

                        <!-- Main_content_#2 -->
                        <h3 class="mt-4">Form View</h3>
                        <div class="card mb-4">
                            <div class="card-header">
                                Form Board | <a href="#">글쓰기</a>
                            </div>
                            <div class="card-body">
                                <p>{{ forms }}</p>
                            </div>
                        </div>

                        <!-- Main_content_#3 -->
                        <h3 class="mt-4">Table View</h3>
                        <div class="card mb-4">
                            <div class="card-header">
                                <i class="fas fa-table me-1"></i>
                                Table Board | <a href="#">글쓰기</a>
                            </div>
                            <div class="card-body">
                                <table id="datatablesSimple">
                                    <thead>
                                        <tr>
                                            <th>순번</th>
                                            <th>제목</th>
                                            <th>작성자</th>
                                            <th>내용</th>
                                            <th>날짜</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                    {% for board in boards %}
                                        <tr>
                                            <td>{{ board.id }}</td>
                                            <td>{{ board.title }}</td>
                                            <td>{{ board.author }}</td>
                                            <td>{{ board.article }}</td>
                                            <td>{{ board.date | date:'Y-m-d' }}</td>
                                        </tr>
                                    {% endfor %}
                                    </tbody>
                                </table>
                            </div>
                        </div>

                        <!-- Main_content_#4 -->

                    </div>
                </main>
            </div>
        </div>
        <!-- Table js source -->
        <script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest" crossorigin="anonymous"></script>
        <script src="{% static 'js/datatables-simple-demo.js' %}"></script>
    </body>
</html>

 


4. form을 이용한 CRUD Control

django 관리자 /admin에서 CRUD control을 직접 template에서 form을 이용하여 수행
model-forms 기반 CRUD control을 위한 views.py, urls.py를 추가하고 template를 생성하여 구현
- index 기준으로 views.py, urls.py CRUD 4종 추가
- template에서는 delete를 제외한 CRU 3종을 추가

전체 List를 보여주는 list_index.html 새로 만들어 다음 CRUD를 구현해보자

C : 글쓰기를 클릭하여 new_board.html에서 form 생성

R : list_index.html의 제목을 클릭하여 detail_board/pk/로 이동

U : detail_board/pk/ 수정을 클릭하여 수정 form 생성

D : detail_board/pk/ 삭제를 클릭하여 해당 record 제거

 

list_index.html
test_index.html을 다른 이름으로 저장하여 Table Board만 남기고 hyperlink를 생성
{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <title>{% block title %}{{ section.title }}{% endblock %}</title>
        <link href="{% static 'css/styles.css' %}" rel="stylesheet" />
    </head>

    <body class="sb-nav-fixed">
        <div id="layoutSidenav">
            <!-- Topbar -->
            <nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
                <!-- Navbar Brand-->
                <a class="navbar-brand ps-3" href="{% url 'board:test_index' %}" style="color:lightgray; font-size:1.7em">App_Test</a>
                <!-- Navbar Top-->
                <div style="color:darkgray; font-size:2em">Test_title</div>
            </nav>
            <!-- Sidebar -->
            <div id="layoutSidenav_nav">
                <nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
                    <div class="sb-sidenav-menu">
                        <div class="nav">
                            <a class="nav-link" href="#">
                                hyperlink 1
                            </a>
                            <a class="nav-link" href="#">
                                hyperlink 2
                            </a>
                        </div>
                    </div>
                </nav>
            </div>

            <!-- Main_Contents -->
            <div id="layoutSidenav_content">
                <main>
                    <div class="container-fluid px-4">
                        <!-- Main_content_#1 -->
                        
                        <!-- Main_content_#2 -->

                        <!-- Main_content_#3 -->
                        <h3 class="mt-4">Table View</h3>
                        <div class="card mb-4">
                            <div class="card-header">
                                <i class="fas fa-table me-1"></i>
                                Table Board | <a href="{% url 'board:brd_create' %}">글쓰기</a>
                            </div>
                            <div class="card-body">
                                <table id="datatablesSimple">
                                    <thead>
                                        <tr>
                                            <th>순번</th>
                                            <th>제목</th>
                                            <th>작성자</th>
                                            <th>내용</th>
                                            <th>날짜</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                    {% for board in boards %}
                                        <tr>
                                            <td>{{ board.id }}</td>
                                            <td><a href="{% url 'board:brd_read' board.pk %}">{{ board.title }}</a></td>
                                            <td>{{ board.author }}</td>
                                            <td>{{ board.article }}</td>
                                            <td>{{ board.date | date:'Y-m-d' }}</td>
                                        </tr>
                                    {% endfor %}
                                    </tbody>
                                </table>
                            </div>
                        </div>
                        <!-- Main_content_#4 -->

                    </div>
                </main>
            </div>
        </div>
        <!-- Table js source -->
        <script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest" crossorigin="anonymous"></script>
        <script src="{% static 'js/datatables-simple-demo.js' %}"></script>
    </body>
</html>

 

browser : localhost:8000/board/list_index/

 

 

 

board/forms.py
from django import forms
from .models import BoardTest


class BoardTestForm(forms.ModelForm):

	class Meta:
		model = BoardTest
		fields = ['author','title', 'article']

		widgets = {
			'author'   : forms.TextInput(attrs={'class':'form-control', 'style':'width: 30em'}),
			'title'    : forms.TextInput(attrs={'class':'form-control', 'style':'width: 30em'}),
			'article'  : forms.Textarea(attrs={'class':'form-control', 'style':'width: 80em', 'rows':10}),
		}

		labels = {
			'author'   : '작성자',
			'title'    : '제목',
			'article'  : '내용',
			'date'     : '날짜',
		}

 

board/views.py
from django.shortcuts import render, redirect

from .models import BoardTest
from .forms import BoardTestForm

# Create your views here.
def test_index(request):
	boards = BoardTest.objects.all()
	forms  = BoardTestForm()
	ctx = {'boards':boards, 'forms':forms}
	return render(request, 'board/test_index.html', ctx)

def list_index(request):
	boards = BoardTest.objects.all()
	ctx = {'boards':boards}
	return render(request, 'board/list_index.html', ctx)

def brd_create(request):
	boards = BoardTest.objects.all()
	if request.method == 'POST':
		form = BoardTestForm(request.POST)
		if form.is_valid():
			board_create = BoardTest()
			board_create.author  = form.cleaned_data['author']
			board_create.title   = form.cleaned_data['title']
			board_create.article = form.cleaned_data['article']
			board_create.save()
			return redirect('board:list_index')
	else:
		form    = BoardTestForm()
		boards  = BoardTest.objects.all()
		ctx = {'form':form, 'boards':boards}
		return render(request, 'board/board_create.html', ctx)


def brd_read(request,pk):
	boards      = BoardTest.objects.all()
	board_read  = BoardTest.objects.get(pk=pk)
	ctx = {'boards':boards,'board_read':board_read}
	return render(request, 'board/board_read.html', ctx)

def brd_update(request,pk):
	boards       = BoardTest.objects.all()
	board_upate  = BoardTest.objects.get(pk=pk)
	if request.method == 'POST':
		form = BoardTestForm(request.POST)
		if form.is_valid():
			board_upate.author = form.cleaned_data['author']
			board_upate.title   = form.cleaned_data['title']
			board_upate.article = form.cleaned_data['article']
			board_upate.save()
			return redirect('board:list_index')
	else:
		form    = BoardTestForm(instance=board_upate)
		boards  = BoardTest.objects.all()
		ctx = {'form':form, 'boards':boards}
		return render(request, 'board/board_update.html', ctx)
	

def brd_delete(request,pk):
	board_del = BoardTest.objects.get(pk=pk)
	board_del.delete()
	return redirect('board:list_index')

 

board/urls.py
from django.urls import path
from . import views

app_name = 'board'

urlpatterns = [
    path('test_index/', views.test_index, name='test_index'),
    path('list_index/', views.list_index, name='list_index'),
    path('brd_create/', views.brd_create, name='brd_create'),
    path('brd_read/<int:pk>/', views.brd_read, name='brd_read'),
    path('brd_read/<int:pk>/update', views.brd_update, name='brd_update'),
    path('brd_read/<int:pk>/delete', views.brd_delete, name='brd_delete'),
]

 

templates 4종은 body의 <main></main> 부분만 수정
-1- board_create
-2- board_read/<int:pk>/
-3- board_read/<int:pk>/update
board_read/<int:pk>/delete : template가 필요없음

 

-1- board_create
board/templates/board/board_create.html
- 글쓰기 hyperlink
- post method를 이용한 새글 작성 form
<main>
    <div class="container-fluid px-4">
        <!-- Main_content_#1 -->

        <!-- Main_content_#2 -->

        <!-- Main_content_#3 -->
        <h3 class="mt-4">Table View</h3>
        <div class="card mb-4">
            <div class="card-header">
                <i class="fas fa-table me-1"></i>
                Table Board | <a href="{% url 'board:brd_create' %}">글쓰기</a>
            </div>
            <div class="card-body">
                <table id="datatablesSimple">
                    <thead>
                        <tr>
                            <th>순번</th>
                            <th>제목</th>
                            <th>작성자</th>
                            <th>내용</th>
                            <th>날짜</th>
                        </tr>
                    </thead>
                    <tbody>
                    {% for board in boards %}
                        <tr>
                            <td>{{ board.id }}</td>
                            <td><a href="{% url 'board:brd_read' board.pk %}">{{ board.title }}</a></td>
                            <td>{{ board.author }}</td>
                            <td>{{ board.article }}</td>
                            <td>{{ board.date | date:'Y-m-d' }}</td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
        <!-- Main_content_#4 -->
        <div class="card mb-4">
            <div class="card-header">
                <form method="POST">
                  {% csrf_token %}
                  {{ form.as_p }}
                  <a href="{% url 'board:list_index' %}"><button type="submit">생성</button></a>
                </form>
            </div>
        </div>
    </div>
</main>

 

browser : localhost:8000/board/brd_create/

 

-2- board_read/<int:pk>/
board/templates/board/board_read.html
- form field 내용 표시
- 수정 | 삭제 hyperlink
<main>
    <div class="container-fluid px-4">
        <!-- Main_content_#1 -->

        <!-- Main_content_#2 -->

        <!-- Main_content_#3 -->
        <h3 class="mt-4">Table View</h3>
        <div class="card mb-4">
            <div class="card-header">
                <i class="fas fa-table me-1"></i>
                Table Board | <a href="{% url 'board:brd_create' %}">글쓰기</a>
            </div>
            <div class="card-body">
                <table id="datatablesSimple">
                    <thead>
                        <tr>
                            <th>순번</th>
                            <th>제목</th>
                            <th>작성자</th>
                            <th>내용</th>
                            <th>날짜</th>
                        </tr>
                    </thead>
                    <tbody>
                    {% for board in boards %}
                        <tr>
                            <td>{{ board.id }}</td>
                            <td><a href="{% url 'board:brd_read' board.pk %}">{{ board.title }}</a></td>
                            <td>{{ board.author }}</td>
                            <td>{{ board.article }}</td>
                            <td>{{ board.date | date:'Y-m-d' }}</td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
        <!-- Main_content_#4 -->
        <div class="card mb-4">
            <div class="card-header">
                <span style="font-size:1.3em">{{ board_read.title }} | {{ board_read.author }}</span><br>
                <span style="font-size:0.9em"><a href="{% url 'board:brd_update' board_read.pk %}">수정</a> | <a href="{% url 'board:brd_delete' board_read.pk %}">삭제</a></span>
            </div>
            <div class="card-body">
                {{ board_read.article }}
            </div>
        </div>
    </div>
</main>

 

browser : localhost:8000/board/brd_read/1/

 

-3- board_read/<int:pk>/update
board/templates/board/board_update.html
- post method를 이용한 수정 작성 form
<main>
    <div class="container-fluid px-4">
        <!-- Main_content_#1 -->

        <!-- Main_content_#2 -->

        <!-- Main_content_#3 -->
        <h3 class="mt-4">Table View</h3>
        <div class="card mb-4">
            <div class="card-header">
                <i class="fas fa-table me-1"></i>
                Table Board | <a href="{% url 'board:brd_create' %}">글쓰기</a>
            </div>
            <div class="card-body">
                <table id="datatablesSimple">
                    <thead>
                        <tr>
                            <th>순번</th>
                            <th>제목</th>
                            <th>작성자</th>
                            <th>내용</th>
                            <th>날짜</th>
                        </tr>
                    </thead>
                    <tbody>
                    {% for board in boards %}
                        <tr>
                            <td>{{ board.id }}</td>
                            <td><a href="{% url 'board:brd_read' board.pk %}">{{ board.title }}</a></td>
                            <td>{{ board.author }}</td>
                            <td>{{ board.article }}</td>
                            <td>{{ board.date | date:'Y-m-d' }}</td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
        <!-- Main_content_#4 -->
        <div class="card mb-4">
            <div class="card-header">
                <form method="POST">
                  {% csrf_token %}
                  {{ form.as_p }}
                  <a href="{% url 'board:list_index' %}"><button type="submit">수정</button></a>
                </form>
            </div>
        </div>
    </div>
</main>

 

browser : localhost:8000/board/brd_read/3/update/

 

board_read/<int:pk>/delete
- template가 필요없음
- 삭제 클릭

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함