일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 최성재
- everybody wants you
- 봉준호감독통역
- 필리핀사망
- parasite
- 우한코로나
- 코로나19
- 신종코로나
- Bolton
- 우한 코로나
- 웨일즈
- 코로나바이러스
- 진짜영웅
- 정은경 본부장님
- 미중
- 어서와한국은처음이지
- 우한코로나바이러스
- 전염병
- red hearse
- 치앙마이
- 우한
- cnn
- 코로나
- 중국외교부
- wuhan
- 봉준호감독통역사
- 조현병
- sharonchoi
- 창궐
- 확진자수
- Today
- Total
오지's blog
장고(django)를 이용한 게시판 개발(CBV - Class-BasedView) 본문
MVC(Model View Controler)에서 웹페이지에 해당하는 View는 Function Based View와 Class Based View가 있는데 두개의 차이는 이름에서도 알수 있는데 함수를 이용한 뷰인지 클래스를 이용한 뷰인지의 차이이다
이 자료에서는 클래스를 이용한 뷰를 이용하는데 장고에서 만들어진 클래스를 상속하여 필요한 부분만 재정의 할것이므로 아주 쉽게 게시판을 만들수 있다.
1. 장고 맛보기 - 초기 프로젝트 실행해보기
step1. 장고 프로젝트 생성
Step2. 파이썬 가상환경 생성(참고. 파이참에서는 장고프로젝트 생성시 가상환경 자동적으로 생성됨)
python -m venv venv
Step4. 장고 라이브러리 설치
pip install django
Step5. 장고 초기 프로젝트 실행해보기
python manage.py runserver
브라우저
http://127.0.0.1:8000/
2. html의 공통점 묶어서 라이브러리 형식으로 만들기
base folder/templates폴더에 base.html생성
아래 코드 삽입
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>게시판</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Nanum+Pen+Script&display=swap" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<style>
div {
font-family: 'Nanum Pen Script', cursive;
}
</style>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
2. 본격적으로 장고를 이용한 게시판 개발
Step0. 게시판 개발에 필요한 라이브러리 설치
게시판에 이미지도 업로드 할수 있도록 이미지업로드를 이용한 pillow 라이브러리 설치 필요
python -m pip install Pillow
Step1. 게시판 어플 생성
참고. 프로젝트이름을 이미 bbs로 생성햇기때문에 이때 설정파일이 들어있는 폴더이름이 bbs가 bbs로 app를 생성할수가 없었다. 그래서 생성파일들이 있는 폴더를 config로 이름을 바꾸었다.
python manage.py startapp article
Step2. settings.py에 생성한 app 등록
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'article',
]
Step3. bbs를 위한 모델 생성
model.py
from django.db import models
from django.utils.timezone import now
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=256)
pub_date = models.DateTimeField(default=now())
update_date = models.DateTimeField(default=now())
content = models.TextField()
img = models.ImageField(upload_to="media/", blank=True)
def __str__(self):
return self.title
Step4. 장고에서 제공하는 어드민 페이지를 위한 admin.py에 관련 코드 생성
admin.py
from django.contrib import admin
from .models import Article
# Register your models here.
admin.site.register(Article)
Step5. html파일들을 위해 bbs폴더내에 templates폴더를 생성한다.
Step6. View에 CRUD를 위한 코드 생성
아래 코드에도 알수 있다시피 대부분 django에서 제공하는 기능을 재정의 한것(재사용)이기 때문에 코드가 굉장히 간결하다.
url.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', article_views.index_view ,name="index"),
path('create/', article_views.ArticleCreateView.as_view() ,name="create"),
path('detail/<int:pk>', article_views.ArticleDetailView.as_view() ,name="detail"),
path('update/<int:pk>', article_views.ArticleUpdateView.as_view() ,name="update"),
path('delete/<int:pk>', article_views.ArticleDeleteView.as_view() ,name="delete"),
path('list/', article_views.ArticleListView.as_view(), name="list"),
]
views.py
from django.shortcuts import render, redirect
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from .models import Article
from django.utils.timezone import now
from django.urls import reverse, reverse_lazy
# Create your views here.
class ArticleCreateView(CreateView):
model = Article
fields = ['title', 'content', 'img']
template_name = 'create.html'
def get_success_url(self):
return reverse('detail', kwargs={'pk':self.object.pk})
class ArticleDetailView(DetailView):
model = Article
template_name = 'detail.html'
def get_context_date(self, **kwargs):
context = super().get_context_data(**kwargs)
context['update_date'] = now()
return context
class ArticleUpdateView(UpdateView):
model = Article
fields = ['title', 'content', 'img']
template_name = 'update.html'
def get_success_url(self):
return reverse('detail', kwargs={'pk':self.object.pk})
class ArticleDeleteView(DeleteView):
model = Article
template_name = 'delete.html'
success_url = reverse_lazy('index')
def get_success_url(self):
return reverse('list')
class ArticleListView(ListView):
model = Article
paginate_by = 10
template_name = 'list.html'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data()
return context
def index_view(request):
return render(request, 'index.html')
각각 html 생성
create.html
{% extends 'base.html' %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="저장">
</form>
{% endblock %}
detail.html
{% extends 'base.html' %}
{% block content %}
title: {{ object.title }}<br>
published_date: {{ object.pub_date }}<br>
updated_date: {{ object.update_date }}<br>
content: {{ object.content }}<br>
image: <img src="{{ object.img }}" alt=""><br>
<a href="{% url 'update' object.id %}">공지 수정</a><br>
<a href="{% url 'delete' object.id %}">접수 취소</a></a>
<a href="{% url 'list' %}">저장</a><br>
{% endblock %}
update.html
{% extends 'base.html' %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="저장">
</form>
{% endblock %}
delete.html
{% extends 'base.html' %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<div>{{ object.title }}</div>
<div>{{ object.pub_date }}</div>
<div>{{ object.update_date }}</div>
<div>{{ object.content }}</div>
<input type="submit" value="접수 취소">
</form>
{% endblock %}
list.html
{% extends 'base.html' %}
{% block content %}
<h1>Notice List</h1>
{% for notice in object_list %}
<li>{{ notice.pub_date}}{{ notice.title }} <a href="{% url 'detail' notice.pk %}">내용보기</a></li>
{% empty %}
<li>empty notice</li>
{% endfor %}
{% endblock %}
Step7. 웹서버 실행을 위한 DB내 스키마 생성
python manage.py makemigrations
python manage.py migrate
Step8. 웹서버 실행을 위해 index페이지 생성
article/templates폴더내에 index.html파일 생성
{% extends 'base.html' %}
{% block content %}
<a href="{% url 'create' %}">새글쓰기</a>
{% endblock %}
view생성
웹서버를 처음 실행했을대의 응답을 index.html로 주겠다는 의미
views.py
def index_view(request):
return render(request, 'index.html')
url등록
url.py
index로 연결하기 위한 설정 추가
path('', article_views.index_view ,name="index"),
3. 웹서버 실행 및 CRUD
Step1.웹서버 실행
python manage.py runserver
이때 발견은 워닝
class Notice(models.Model):
title = models.CharField(max_length=256)
pub_date = models.DateTimeField(default=now())
update_date = models.DateTimeField(default=now())
content = models.TextField()
img = models.ImageField(upload_to="media/", blank=True)
여기서 now()이 부분을 now로 수정하여 해결
class Notice(models.Model):
title = models.CharField(max_length=256)
pub_date = models.DateTimeField(default=now)
update_date = models.DateTimeField(default=now)
content = models.TextField()
img = models.ImageField(upload_to="media/", blank=True)
전체 소스코드는 github 저장소를 참고해주세요.