goodthings4me.tistory.com
[python] 장고(django)로 게시판 만들어보기
MariaDB와 파이썬 장고(django) 프레임워크를 이용한 간단한 게시판 만들기
◆ 작업할 디렉토리 만들기
- 탐색기에서 장고 게시판 코딩을 할 디렉토리(djangoBoard)를 만들고,
- VS Code를 실행한 후 '폴더열기'로 해당 폴더를 연다.
◆ 가상환경 설정 및 장고 설치
## 가상환경 설정
C:\Users\xxxxxx\django\djangoBoard>python -m venv venv
## 파이썬 버전 확인
C:\Users\xxxxxx\django\djangoBoard>python -V
Python 3.8.8
## 가상환경 실행
C:\Users\xxxxxx\django\djangoBoard>cd venv/Scripts
(venv) C:\Users\xxxxxx\django\djangoBoard\venv\Scripts>activate
(venv) C:\Users\xxxxxx\django\djangoBoard\venv\Scripts>cd..
(venv) C:\Users\xxxxxx\django\djangoBoard\venv>cd..
## 장고 버전 확인
(venv) C:\Users\xxxxxx\django\djangoBoard>django-admin --version
3.1
## 장고 설치 (버전 3.2)
(venv) C:\Users\xxxxxx\django\djangoBoard>pip install django==3.2
Collecting django==3.2
Using cached Django-3.2-py3-none-any.whl (7.9 MB)
Collecting pytz
Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
Collecting sqlparse>=0.2.2
Using cached sqlparse-0.4.2-py3-none-any.whl (42 kB)
Collecting asgiref<4,>=3.3.2
Using cached asgiref-3.4.1-py3-none-any.whl (25 kB)
Installing collected packages: pytz, sqlparse, asgiref, django
Successfully installed asgiref-3.4.1 django-3.2 pytz-2021.1 sqlparse-0.4.2
WARNING: You are using pip version 20.2.3; however, version 21.2.4 is available.
You should consider upgrading via the 'c:\users\xxxxxx\django\djangoboard\venv\scripts\python.exe -m pip install --upgrade pip' command.
## pip 업그레이드
(venv) C:\Users\xxxxxx\django\djangoBoard>python -m pip install --upgrade pip
Collecting pip
Using cached pip-21.2.4-py3-none-any.whl (1.6 MB)
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 20.2.3
Uninstalling pip-20.2.3:
Successfully uninstalled pip-20.2.3
Successfully installed pip-21.2.4
(venv) C:\Users\xxxxxx\django\djangoBoard>pip list
Package Version
---------- -------
asgiref 3.4.1
Django 3.2
pip 21.2.4
pytz 2021.1
setuptools 49.2.1
sqlparse 0.4.2
## 장고 프로젝트 생성
(venv) C:\Users\xxxxxx\django\djangoBoard>django-admin startproject config .
◆ MariaDB 설치
sqlite3 대신 MariaDB(MySQL과 동일한 엔진 사용)를 사용하기 위해 공식사이트에서 Windows 64비트 버전을 다운로드 한 후 설치한다. https://mariadb.org/
- MariaDB Server Version 10.6.4 (52MB)
- MariaDb 설치 시 HeidiSQL DB 관리 툴이 기본적으로 설치되기 때문에 DB 관리가 편리하다.(설치 시 root 비번은 꼭 기억할 것)
※ 윈도우10에서 MariaDB 설치
설치 위치 확인 (Browser 버튼으로 설치 위치 변경 가능)
비밀번호를 입력하고, DB character set (Encoding)은 UTF-8 사용으로 체크 Next 클릭
Service Name 등 그대로 두고 Next, Install 클릭
설치 완료 후 윈도우 시작 버튼을 눌러 MariaDB 설치 내용을 확인해본다.
※ HeidiSQL 실행
- 세션 이름은 원하는 이름으로 입력(입력 안해도 되지만..)
- 암호 넣고 '열기' 클릭
- 장고 프로젝트에서 사용할 database 생성 (세션이름 마우스 우클릭 후 새로생성 > 데이터베이스)
- 장고 settings.py에서 접속할 데이터베이스 이름임(borameboard)
◆ 장고와 MariaDB 연동을 위해 라이브러리(mysqlclient)를 설치한다.
(venv) C:\Users\xxxxxx\django\djangoBoard>pip install mysqlclient
Collecting mysqlclient
Downloading mysqlclient-2.0.3-cp38-cp38-win_amd64.whl (179 kB)
|████████████████████████████████| 179 kB 6.4 MB/s
Installing collected packages: mysqlclient
Successfully installed mysqlclient-2.0.3
- 이 패키지 설치를 안하면 database 연결이 안됨
◆ 장고 sqlite3 대신 사용할 db 접속 정보 설정하기 - settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
#위 코드를 아래처럼 수정한다.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'borameboard',
'USER': 'root',
'PASSWORD': '**********',
'HOST': 'localhost',
'PORT': '3306'
}
}
● django 연동 기본 DB 초기화 (migrate 명령) 및 테스트 서버 구동(runserver)
- HeidiSQL에서 borameboard database가 필히 생성되어있어야 함
(venv) C:\Users\xxxxxx\django\djangoBoard>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
(venv) C:\Users\xxxxxx\django\djangoBoard>python manage.py run server
- admin, auth, board, contenttypes, sessions 관련 모델(db)이 생성됨
※ 브라우저에서 127.0.0.1:8000 또는 localhost:8000 으로 접속
◆ 사용자(관리자) 계정 설정
(venv) C:\Users\xxxxxx\django\djangoBoard>python manage.py createsuperuser
사용자 이름 (leave blank to use 'xxxxxx'): admin
이메일 주소:
Password:
Password (again):
Superuser created successfully.
- 관리자 계정으로 접속
◆ 게시판 앱(borameboard) 생성 및 앱 등록
(venv) C:\Users\xxxxxx\django\djangoBoard>python manage.py startapp borameboard
- borameboard 생성 후 settings.py에 앱 등록
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'borameboard',
]
◆ URL Conf 설정
# config>urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('board/', include('borameboard.urls')),
]
- 127.0.0.1:8000/board 접속 시 borameboard 앱의 urls.py로 보내도록 경로 지정
- borameboard 앱에 urls.py를 만들고,
User Interface인 html 파일을 만들 templates 폴더 / borameboard 폴더를 만든다.
# borameboard>urls.py
from django.urls import path
from . import views
app_name = 'borame_board'
urlpatterns = [
path('', views.index, name='index'),
]
◆ views.py 작성
from django.shortcuts import render
def index(request):
context = {'board_list': '테스트입니다.'}
return render(request, 'borameboard/index.html', context)
- templates / borameboard 밑에 index.html 템플릿 파일을 생성하고, views.py의 index() 반환값이 출력되는지 확인한다.
# index.html
<html>
<body>
{{board_list}}
</body>
</html>
- 127.0.01:8000/board 로 사이트 접속
◆ 모델 (DB) 생성 - modes.py
- 장고의 ORM 기능인 models를 통해 게시판 글을 관리하는 DB를 생성한다.
- 장고에서 모든 database table은 모델(Model)로 관리할 수 있다.
- 장고에서는 primary key를 관리하는 id 속성이 자동으로 지정되어 관리된다.
# id = models.AutoField(primary_key=True)
- 다른 컬럼(필드)에 primary key를 부여하고 싶으면 해당 필드에 primary_key=True 옵션을 준다.
# models.CharField는 문자열 필드,
# models.TextField는 문장을 입력할 수 있는 필드(textarea)
# DateTimeField는 날짜 필드를 의미한다.
from django.db import models
class Board(models.Model):
title = models.CharField(max_length=200, verbose_name='글 제목', help_text='* 제목은 최대 100자 이내')
author = models.CharField(max_length=100, verbose_name='글쓴이')
content = models.TextField(verbose_name='글 내용')
published_date = models.DateTimeField(auto_now=True, verbose_name='등록(수정)일')
def __str__(self):
return self.title
- __str__() 함수는 객체가 생성되면 객체를 문자열로 반환해주는 함수인데, title(제목)을 반환하도록 지정함
(venv) C:\Users\xxxxxx\django\djangoBoard>python manage.py makemigrations
Migrations for 'borameboard':
borameboard\migrations\0001_initial.py
- Create model Board
(venv) C:\Users\xxxxxx\django\djangoBoard>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, borameboard, contenttypes, sessions
Running migrations:
Applying borameboard.0001_initial... OK
- makemigrations 명령으로 생성된 모델을 마이그레이션 객체로 변환, migrate 명령으로 데이터베이스에 table 생성
◆ admin 페이지에 등록
from django.contrib import admin
from .models import Board
@admin.register(Board)
class BoardAdmin(admin.ModelAdmin):
list_display = ['id', 'title', 'author', 'published_date']
list_display_links = ['id', 'title']
list_per_page = 10
- list_display : Admin 목록에 보여질 필드 목록
- list_display_links : 목록 내에서 링크로 지정할 필드 목록
- list_per_page : 페이지 별로 보여질 개수 (디폴트 100)
◆ models 마이그레이트 후 어드민 계정 접속
- Boards 클릭
- BOARD 추가 버튼 클릭하여 테스트 데이터 입력
◆ Django Template 상속
- 템플릿 파일의 중복 내용을 상속을 통해 중복되지 않도록 할 수 있다.
- 전체 레이아웃(부모 템플릿) 내에 {% block 블럭 영역 명칭 %} {% endblock %}으로 정의 후 각 템플릿(자식 템플릿)에서 다음과 같이 재정의하여 사용
{% extends '부모 템플릿(경로)' %}
{% block 블럭 영역 명칭 %}
{% endblock %}
- djangoBoard 내 하위 폴더 layout을 만들고 장고 전체에서 사용할 base.html 템플릿 파일을 생성한다.
# base.html 템플릿 파일 경로 설정 : settings.py에 디렉토리 경로 지정
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ ],
에서
'DIRS': [ ], 부분을
'DIRS': [os.path.join(BASE_DIR, 'layout')], 처럼 수정한다.
# import os 필요함
- base.html 파일을 전체 레이아웃으로 사용하기 위해 bootstrap을 적용한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Borame Board</title>
</head>
<body>
<div class="container-fluid">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">LOGO</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Menu1</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Menu2</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">borameBoard</a>
</li>
</ul>
</div>
</div>
</nav>
</div>
<div class="container">
{% block content %}
{% endblock %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
- Navbar 종류 중 하나를 선택하여 복사한 후 <div class="container-fluid"> 밑에 붙여넣기
- 부트스트랩 사이트(https://getbootstrap.com/docs/5.1/getting-started/introduction/)에서 css와 js 링크를 복사하여 붙여 넣고 사용함
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>
◆ views.py 내용 수정
from django.shortcuts import render
from .models import Board
def index(request):
board_list = Board.objects.all().order_by('-id')
context = {'board_list': board_list}
return render(request, 'borameboard/index.html', context)
- Board 객체 매니저인 objects를 사용하여 해당 db table의 데이터 추출 QuerySet을 변수 board_list에 저장한다.
# 데이터 전체(all())를 id 역순으로 정렬(order_by('-id'))하는 QuerySet
- 추출한 쿼리셋 데이터를 index.html로 렌더링하여 브라우저로 보여준다.
◆ index.html 내용 수정
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row pt-4 my-3">
<div class="col-md-12">
<h3>게시판</h3>
</div>
</div>
<div class="row my-3">
<table class="table table-hover table-bordered">
<thead>
<th>No</th>
<th>제목</th>
<th>작성자</th>
<th>내용</th>
<th>발행일</th>
<th>비고</th>
</thead>
<tbody>
{% for post in board_list %}
<tr>
<td>{{ forloop.revcounter }}</td>
<td><a href="#">{{ post.title }}</a></td>
<td>{{ post.author }}</td>
<td>{{ post.content|truncatewords:5 }}</td>
<td>{{ post.published_date|date:"Y-m-d" }}</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
◆ 127.0.0.1:8000 으로 접속 시 index.html로 바로 접속하도록 path 설정
- borameboard의 urls.py에서 path를 받아 views.py에서 redirect() 함수로 처리해도 되지만,
- config / urls.py 에서 아래처럼 path('', lambda r: redirect('borame_board:index')), 추가하면 바로 redirect 처리할 수도 있다.
* from django.shortcuts import redirect 추가하고, lambda 함수와 redirect 함수 이용
from django.contrib import admin
from django.urls import path, include
from django.shortcuts import redirect
urlpatterns = [
path('admin/', admin.site.urls),
path('', lambda r: redirect('borame_board:index')),
path('board/', include('borameboard.urls')),
]
◆ 글 등록을 위해 urls.py 수정
- path('regist/', views.regist, name='regist'), 추가
◆ index.html 템플릿 파일 하단에 '글 등록' 버튼 추가
<div style="padding: 2px 20px; float:right;">
<a href="{% url 'borame_board:regist' %}" class="btn btn-primary">글 등록</a>
</div>
◆ 글 등록은 장고 폼(forms.ModelForm)을 사용해본다.
- borameboard 앱에 forms.py 파일을 생성한다.
from django import forms
from django.forms import widgets
from .models import Board
class RegistForm(forms.ModelForm):
class Meta:
model = Board
fields = ['title', 'author', 'content'] # '__all__'
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'author': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 10}),
}
- Model 클래스와 유사하게 Form 클래스 정의 (HTML Form 요소를 파이썬 클래스화)
- 장고 models 에 대한 form을 생성하기 위해 모델명을 import하고, 보여 줄 컬럼(필드)를 지정한다.('__all__'인 경우 전체 지정됨)
- 템플릿에서 보여질 html의 요소(Element)를 지정하기 위해 widgets을 import 하고 설정한다.
◆ 등록 폼 템플릿 추가
- borameboard / templates / borameboard / regist_form.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row pt-4 my-3">
<div class="col-md-12">
<h3>글 등록</h3>
</div>
</div>
<div class="row my-3"></div>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<div style="padding: 5px 50px; float:right;">
<input class="btn btn-primary" type="submit" value="글 등록">
<a href="#" class="btn btn-primary">글 목록</a>
</div>
</form>
</div>
</div>
{% endblock %}
- csrf_token : (Cross Site Request Forgeries) 사이트 간 요청 위조 공격 막기 위함
◆ 입력된 글 등록(처리)를 위해 views.py 에 regist() 추가
from borameboard.models import Board
from django.shortcuts import render,redirect
from .models import Board
from .forms import RegistForm
def index(request):
board_list = Board.objects.all().order_by('-id')
context = {'board_list': board_list}
return render(request, 'borameboard/index.html', context)
def regist(request):
if request.method == 'POST':
form = RegistForm(request.POST)
if form.is_valid():
post = form.save()
return redirect('borame_board:index')
else:
form = RegistForm()
context = {'form': form,}
return render(request, 'borameboard/regist_form.html', context)
◆ 글 내용 보기
- borameboard / urls.py 에 path('detail/<int:pk>/', views.detail, name='detail'), 추가
- 글 목록(리스트)에서 글 제목을 클릭하면 글의 내용을 볼 수 있도록 하기 위해
index.html의 <td><a href="#">{{ post.title }}</a></td> 부분을
<td><a href="{% url 'borame_board:detail' post.id %}">{{ post.title }}</a></td> 로 수정한다.
◆ views.py 에 detail() 추가
def detail(request, pk):
board_list = get_object_or_404(Board, id=pk)
context = {'board_list': board_list}
return render(request, 'borameboard/detail.html', context)
- views 내에서 특정 조건에 맞는 모델 인스턴스를 가져오려고 할 때는 항상 get_object_or_404() 를 쓴다.
* 글 삭제 또는 글이 없어서 발생하는 오류 코드(status code)가 500이 아닌 404로 되도록 하기 위함
* get_object_or_404 추가 (from django.shortcuts import render, redirect, get_object_or_404)
- 글 세부 내용 보기 템플릿 - borameboard / templates / borameboard / detail.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row pt-4 my-3">
<div class="col-md-12">
<h3>글 세부 내용</h3>
</div>
</div>
<div class="row my-3">
<table class="table table-bordered">
<tr>
<td>[글 제목] : {{ board_list.title }}</td>
</tr>
<tr>
<td>
<p>[글 내용]</p>
{{ board_list.content|linebreaks }}
<p><small style="color:silver;text-align:right;">[{{ board_list.published_date|date:"Y-m-d H:i:s" }}]</small></p>
</td>
</tr>
</table>
</div>
<div style="padding: 2px 20px; float:right;">
<a href="{% url 'borame_board:index' %}" class="btn btn-primary">글 목록</a>
</div>
</div>
{% endblock %}
◆ 글 수정 기능
- 글 수정을 위해 borameboard / urls.py 에
path('edit/<int:pk>/', views.edit, name='edit'), 추가
- 글 목록에서 '비고' 내의 '수정' 링크(버튼)를 클릭하면, 수정페이지로 전환되고 수정할 글의 id를 urls에 전달되도록 위해 index.html의 비고 부분에 <a href="{% url 'borame_board:edit' post.id %}" class="btn btn-outline-info btn-sm">수정</a> 를 추가한다.
views.py 에 edit() 추가
def edit(request, pk):
post = get_object_or_404(Board, id=pk)
if request.method == 'POST':
form = RegistForm(request.POST, instance=post)
if form.is_valid():
post = form.save()
return redirect('borame_board:index')
else:
form = RegistForm(instance=post)
context = {'form': form,}
return render(request, 'borameboard/edit_form.html', context)
- id=pk인 모델 인스턴스를 get_object_or_404()로 가져와서 post 변수에 저장하고, 이 인스턴스 변수를 기준으로 폼을 생성한다. ( instance=post)
- 수정 폼은 등록 폼을 그대로 활용하도록 작성한다.
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row pt-4 my-3">
<div class="col-md-12">
<h3>글 수정</h3>
</div>
</div>
<div class="row my-3"></div>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<div style="padding: 5px 50px; float:right;">
<input class="btn btn-primary" type="submit" value="글 수정">
<a href="{% url 'borame_board:index' %}" class="btn btn-primary">글 목록</a>
</div>
</form>
</div>
</div>
{% endblock %}
◆ 글 삭제 기능
- 글 삭제 기능도 글 목록의 '비고' 내에 '삭제' 링크(버튼)를 만들어서 처리한다.
* index.html의 비고 부분에 <a href="{% url 'borame_board:delete' post.id %}" onclick="if(!confirm('정말 삭제하시겠습니까?')){return false;}" class="btn btn-outline-danger btn-sm">삭제</a>추가
- urls.py 에 path('delete/<int:pk>/', views.delete, name='delete'), 추가
views.py 에 delete() 추가
def delete(request, pk):
post = get_object_or_404(Board, id=pk)
post.delete()
return redirect('borame_board:index')
◆ base.html 상단 메뉴의 Home과 borameboard에 게시판 리스트 페이지를 링크한다.
<a class="nav-link active" aria-current="page" href="#">Home</a>
<a class="nav-link" href="#">borameBoard</a>
아래 처럼 수정
<a class="nav-link active" aria-current="page" href="{% url 'borame_board:index' %}">Home</a>
<a class="nav-link" href="{% url 'borame_board:index' %}">borameBoard</a>
◆ 페이징 처리
- 사전 작업 : 장고 쉘(shell)을 이용한 데이터 입력
(venv) C:\Users\xxxxxxdjango\djangoBoard>python manage.py shell
Python 3.8.8 (default, Apr 13 2021, 15:08:03) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
>>> from django.utils import timezone
>>> from borameboard.models import Board
>>> query = Board(title='페이징 처리', author='2000', content='페이징 처리 데이터 입력', published_date=timezone.now())
>>> query.save()
>>> Board.objects.all()
<QuerySet [<Board: 김장용품>, <Board: 반려견 애정템>, <Board: 가성비 좋은 노트북>, <Board: 크리스마스 선물>, <Board: 맥북
프로 16인치>, <Board: 갤럭시 워치4>, <Board: 페이징 처리>]>
>>> for i in range(60):
... query = Board(title='페이징 처리-'+str(i), author='2000', content='페이징 처리 데이터 입력_'+str(i), published_date=timezone.now())
... query.save()
...
>>> Board.objects.all()
<QuerySet [<Board: 김장용품>, <Board: 반려견 애정템>, <Board: 가성비 좋은 노트북>, <Board: 크리스마스 선물>, <Board: 맥북
프로 16인치>, <Board: 갤럭시 워치4>, <Board: 페이징 처리>, <Board: 페이징 처리-0>, <Board: 페이징 처리-1>, <Board: 페이징
처리-2>, <Board: 페이징 처리-3>, <Board: 페이징 처리-4>, <Board: 페이징 처리-5>, <Board: 페이징 처리-6>, <Board: 페이징 처
리-7>, <Board: 페이징 처리-8>, <Board: 페이징 처리-9>, <Board: 페이징 처리-10>, <Board: 페이징 처리-11>, <Board: 페이징 처
리-12>, '...(remaining elements truncated)...']>
>>>
# 장고에서는 파이썬 쉘이 아닌 장고 쉘을 이용한다. (python manage.py shell 로 쉘에 진입 후 작업 진행)
※ 장고의 ORM 관련 메서드 간략하게 알아보기
all()
해당 table의 데이타 전체 가져오기
데이터 전체를 QuerySet 타입으로 반환
dict 타입 사용 방법으로 개별 row를 출력할 수 있다.
rs = Board.objects.all()
print(rs[0]['title'])
get()
row 1개만 가져오기
QuerySet이 아닌 단일 행(모델 타입) 반환
반환 값(row 수)이 1개 이상일 경우 에러 발생함
rs = Board.objects.get(id=1)
print(rs.title)
filter()
특정 조건에 맞는 row들을 가져오기
조건에 맞는 여러 행(row) 반환(QuerySet 타입)
rs = Board.objects.filter(title='갤럭시')
또는 Board.objects.all().filter(title='갤럭시') 와 동일, all() 생략 가능
print(rs[0]['title'])
order_by(key)
인자(키)에 따라 데이터 정렬하며, 정렬 키는 나열 가능
기본 정렬은 오름차순이고, 키 앞에 -가 붙으면 내림차순
Board.objects.order_by('id')
value()
특정 컬럼만을 대상으로 값을 반환할 때 사용
QuerySet 타입 반환
Board.objects.value('title')
exclude()
특정 조건을 제외한 나머지 row들을 가져오기
Board.objects.exclude(title='갤럭시')
distinct()
중복된 값은 하나로만 표시하기(SELECT DISTINCT 와 같은 효과)
Board.objects.distinct('title')
first()
데이타들 중 맨 처음에 있는 row만 가져오기
Board.objects.order_by('title').first()
last()
데이타들 중 맨 마지막에 있는 row만 가져오기
Board.objects.filter(title='갤럭시').order_by('-id').first()
count()
데이타의 갯수(row 수) count
Board.objects.count()
Data INSERT 하기
테이블에 해당하는 모델(model)로부터 객체 생성 후, 그 객체의 save() 메서드를 호출한다.
q = Board(title='페이징 처리', author='2000', content='페이징 처리 데이터 입력', published_date=timezone.now())
q.save()
Data UPDATE 하기
업데이트 할 row 객체를 생성하고 변경할 컬럼(필드)를 수정한 후, save() 메서드를 호출한다.
q = Board.objects.get(id=1)
q.title = '갤럭시 워치 4 싸게 구매하기'
q.save()
Date DELETE 하기
데이타를 삭제할 row 객체를 생성하고 delete() 메서드를 호출한다.
q = Board.objects.get(id=2)
q.delete()
- 페이징 처리를 위해 views.py 에서 index() 함수 수정하기
from django.core.paginator import Paginator 추가
def index(request):
page = request.GET.get('page', '1') # 페이지 파라미터 얻기, 없으면 1
board_list = Board.objects.order_by('-id')
# 페이징 처리
paginator = Paginator(board_list, 10) # 페이지당 10개씩 보여주기
page_obj = paginator.get_page(page) # page에 해당하는 페이징 객체 생성
context = {'board_list': page_obj} # 페이징 객체(page_obj) 전달
return render(request, 'borameboard/index.html', context)
# 페이징 객체(page_obj) 속성
count : 총 객체 수
paginator.count : 전체 게시물 개수
paginator.per_page : 페이지당 보여줄 게시물 개수
paginator.page_range : 페이지 범위
number : 현재 페이지 번호
get_page : 페이지 가져오기
page_range : 페이지 리스트(1~)
num_pages: 총 페이지 수
page(n) : n 번째 페이지
previous_page_number : 이전 페이지 번호
next_page_number : 다음 페이지 번호
has_previous : 이전 페이지 유무(boolean)
has_next : 다음 페이지 유무(boolean)
start_index : 현재 페이지 시작 인덱스(1부터 시작)
end_index : 현재 페이지의 끝 인덱스(1부터 시작)
- index.html 수정
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row pt-4 my-3">
<div class="col-md-12">
<h3>게시판</h3>
</div>
</div>
<div class="row my-3">
<table class="table table-hover table-bordered">
<thead>
<th>No</th>
<th>제목</th>
<th>작성자</th>
<th>내용</th>
<th>발행일</th>
<th>비고</th>
</thead>
<tbody>
{% for post in board_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td><a href="{% url 'borame_board:detail' post.id %}">{{ post.title }}</a></td>
<td width="100">{{ post.author }}</td>
<td>{{ post.content|truncatewords:5 }}</td>
<td>{{ post.published_date|date:"Y-m-d" }}</td>
<td width="120">
<a href="{% url 'borame_board:edit' post.id %}" class="btn btn-outline-info btn-sm">수정</a>
<a href="{% url 'borame_board:delete' post.id %}" onclick="if(!confirm('정말 삭제하시겠습니까?')){return false;}"
class="btn btn-outline-danger btn-sm">삭제</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="row">
<div class="col-md-12 ">
<a href="{% url 'borame_board:regist' %}" class="btn btn-outline-secondary">글 등록</a>
</div>
</div>
<!-- 페이징 처리 --->
<div class="row my-3">
<div class="col-md-12 text-center">
{% if board_list.has_previous %}
<a href="?page=1">처음</a>
<a href="?page={{ board_list.previous_page_number }}">이전</a>
{% endif %}
<!-- 페이지리스트 -->
<span style="color:red;font-weight:bold;">{{ board_list.number }}</span>
<span> / </span>
<span style="font-weight:bold;">{{ board_list.paginator.num_pages }}</span>
{% if board_list.has_next %}
<a href="?page={{ board_list.next_page_number }}">다음</a>
<a href="?page={{ board_list.paginator.num_pages }}">끝</a>
{% endif %}
</div>
</div>
</div>
{% endblock %}
'코딩 연습 > 코딩배우기' 카테고리의 다른 글
파이썬 장고(django) 웹 프로그래밍 - 웹 페이지 만들기 # 2 (0) | 2021.11.03 |
---|---|
네이버 검색어 중 자동완성어 추출해보기(with 파이썬) (0) | 2021.10.15 |
파이썬 datetime 모듈과 장고(django) 시간대(use tz) 설정 (0) | 2021.10.11 |
구글에서 원하는 이미지 다운로드 해보기 (with 파이썬) (0) | 2021.10.11 |
VS Code에서 파이썬 가상환경 만들기 (1) | 2021.10.11 |
댓글