-
[python] 장고(django)로 게시판 만들어보기코딩 연습/코딩배우기 2021. 10. 11. 21:12
[python] 장고(django)로 게시판 만들어보기
MariaDB와 파이썬 장고(django) 프레임워크를 이용한 간단한 게시판 만들기
◆ 작업할 디렉토리 만들기
- 탐색기에서 장고 게시판 코딩을 할 디렉토리(djangoBoard)를 만들고,
- VS Code를 실행한 후 '폴더열기'로 해당 폴더를 연다.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 Foundation - MariaDB.org
… Continue reading "MariaDB Foundation"
mariadb.org
- MariaDB Server Version 10.6.4 (52MB)
- MariaDb 설치 시 HeidiSQL DB 관리 툴이 기본적으로 설치되기 때문에 DB 관리가 편리하다.(설치 시 root 비번은 꼭 기억할 것)
※ 윈도우10에서 MariaDB 설치
Next 클릭 Next 클릭 설치 위치 확인 (Browser 버튼으로 설치 위치 변경 가능)
Next 클릭 비밀번호를 입력하고, DB character set (Encoding)은 UTF-8 사용으로 체크 Next 클릭
Next 클릭 Service Name 등 그대로 두고 Next, Install 클릭
설치 완료 후 윈도우 시작 버튼을 눌러 MariaDB 설치 내용을 확인해본다.
(HeidiSQL 설치 확인 및 클릭) ※ HeidiSQL 실행
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.
- 관리자 계정으로 접속
admin 페이지 ◆ 게시판 앱(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 로 사이트 접속
index.html 접속 확인 ◆ 모델 (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 생성
HeidiSQL로 확인 ◆ 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 마이그레이트 후 어드민 계정 접속
등록한 Board Model 확인 - 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 %}
페이징 처리 후 index 페이지 '코딩 연습 > 코딩배우기' 카테고리의 다른 글
파이썬 장고(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