Create 생성, Read 조회, Update 수정, Delete 삭제
웹사이트의 가장 핵심적인 기능
(예) 게시글/댓글 작성, 조회, 삭제, 수정 등
프로젝트 생성
mkdir django
cd django
pyenv local django-envs
django-admin start project costory
cd costory
code .
프로젝트 설정
#settings.py
TIME_ZONE = 'UTC' #지우고
TIME_ZONE = 'Asia/Seoul'
블로그 포스트 관리 앱 생성
python manage.py startapp posts
python manage.py migrate
‘’(root) | 블로그 홈페이지 |
---|---|
/posts/ | 전체 포스트 조회(Read) |
/posts/<post_id> | 개별 포스트 조회(Read) |
/posts/new | 포스트 작성(Create) |
/posts/<post_id>/edit | 포스트 수정(Update) |
/posts/<post_id>/delete | 포스트 삭제(Delete) |
URL 설정하기
#project app의 urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('posts.urls')),
]
#posts app에 urls.py 생성 후 사용
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
# path('', views.index),
# path('posts/', views.post_list),
# path('posts/new', views.post_create),
# path('posts/<int:post_id>/',views.post_detail),
# path('posts/<int:post_id>/edit', views.post_update),
# path('posts/<int:post_id>/delete', views.post_delete)
]
#project app의 models.py
from django.db import models
# Create your models here.
class Post(models.Model):
#글의 제목, 내용, 작성일, 마지막 수정일
title = models.CharField(max_length=50)
content = models.TextField()
dt_created = models.DateTimeField(verbose_name="Date Created",
auto_now_add = True)
dt_modified = models.DateTimeField(verbose_name = 'Date Modified',
auto_now=True)
def __str__(self):
return self.title
admin.py에 모델 등록
#admin.py
from django.contrib import admin
from {project_app}.models import {model_name}
admin.site.register({model_name})
#admin.site.register(Page)
Migrate하기
python manage.py makemigrations
python manage.py migrate
Terminal에서 shell 실행: terminal → new terminal → 터미널에 python manage.py shell 입력
데이터 추가하기
from posts.models import Post
Posts.objects.create(title="첫 포스팅", content="오늘 새 맥북 프로가 왔어요!!!")
전체 데이터 조회
Posts.objects.all().values()
데이터 수정하기
post = Post.objects.get(id=1)
post.title="맥북 프로와 함께하는 첫 포스팅(수정)"
post.save()
관리자 페이지로 데이터 추가하기
python manage.py createsuperuser
Django에서 Model을 정의하면 ORM을 통해 데이터베이스와 소통할 수 있는 API 제공
API: epdlxjqpdltmfmf whwkrgkf Eo tkdydgoTejs dkfodhk rkxdms ahems audfuddj
<model>.objects.all() #모든 데이터 가져오기
<model>.objects.get() #조건에 맞는 데이터 1개 가져오기
Queryset: Django Model의 데이터가 담겨있는 목록
<model>.objects.all() #<model>의 모든 데이터 Queryset 가져오기
Queryset API
Queryset: 데이터베이스로부터 가져온 여러개의 model 데이터
필드 조건 옵션 (Field Lookups): Queryset 연산을 할 때 사용할 수 있는 여러 필드 조건 옵션
Lazy Evaulation, 지연 연산
위에서 작성한 Django의 모든 Query 연산은 병합 (Chain)이 가능함
Post.objects.filter(id__gte=10, content__contains='codeit').order_by('-dt_created').last()
#posts app의 views.py
from django.shortcuts import render
from posts.models import Post #데이터베이스와 소통하기 위해 models을 가져온다
# Create your views here.
def post_list(request):
posts = Post.objects.all()
context = {"posts":posts}
return render(request, 'posts/post_list.html', context=context)
#views.py
from django.shortcuts import render
from posts.models import Post
def post_detail_view(request, post_id):
post = Posts.objects.get(id=post_id)
context = {"post":post}
return render(request, 'posts/post_detail.html', context=context)
#post_details.html
{% extends './base.html' %}
{% block post_container %}
<h2>{{post.title}}</h2>
<div>작성일: {{post.dt_created}}</div>
<hr>
<div>{{post.content|linebreaksbr}}</div>
<hr>
{% endblock post_container %}
#post_list.html
{% extends './base.html' %}
{% load static %}
{% block post_container %}
<h1>글 목록 페이지에요</h1>
<table>
<tr>
<td>제목</td>
<td>작성일</td>
<td>수정일</td>
</tr>
{% for post in posts %}
<tr>
<td>**<a href="/posts/{{post.id}}">**{{post.title}}**</a><**/td>
<td>{{post.dt_created}}</td>
<td>{{post.dt_modified}}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
#post_detail.html
{% extends './base.html' %}
{% block post_container %}
<h2>{{post.title}}</h2>
<div>작성일: {{post.dt_created}}</div>
<hr>
<div>{{post.content|linebreaksbr}}</div>
<hr>
<a href='/posts/'>돌아가기</a>
{% endblock post_container %}
URL의 name 속성: 각각의 URL에 이름을 붙여주는 것
#urls.py
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
# path('', views.index),
path('posts/', views.post_list, name='post-list'),
# path('posts/new', views.post_create),
path('posts/<int:post_id>/',views.post_detail, name='post-detail'),
# path('posts/<int:post_id>/edit', views.post_update),
# path('posts/<int:post_id>/delete', views.post_delete)
]
#post_detail.html
{% extends './base.html' %}
{% block post_container %}
<h2>{{post.title}}</h2>
<div>작성일: {{post.dt_created}}</div>
<hr>
<div>{{post.content|linebreaksbr}}</div>
<hr>
<a **href={% url 'post-list' %}**>돌아가기</a>
{% endblock post_container %}
{% extends './base.html' %}
{% load static %}
{% block post_container %}
<h1>글 목록 페이지에요</h1>
<table>
<tr>
<td>제목</td>
<td>작성일</td>
<td>수정일</td>
</tr>
{% for post in posts %}
<tr>
<td><a href={% url 'post-detail' post.id %}>{{post.title}}</a></td>
<td>{{post.dt_created}}</td>
<td>{{post.dt_modified}}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
폼: 웹페이지에서 사용자의 데이터를 입력받을 수 있는 입력 양식
label & input
<form>
<label>이름</label>
<input type="text">
</form>
for & id
<form>
<label for="title">제목</label>
<input type="text" id="title">
</form>
<form>
<label>제목
<Input type="text">
</label>
</form>
name
<form>
<label for="title">제목</label>
<input type="text" id="title" name="title">
</form>
type
<label for="email">이메일</label>
<input type="email" id="email" name="email">
password
<label for="pwd">비밀번호</label>
<input type="password" id="pwd" name="pwd">
button
<input type="button" value="버튼입니다">
radio
<input type="radio" id="male" name="gender" value="male">
<label for="male">남자</label><br>
<input type="radio" id="female" name="gender" value="female">
<label for="female">여자</label><br>
<input type="radio" id="other" name="gender" value="other">
<label for="other">기타</label>
checkbox
<input type="checkbox" id="lang1" name="lang1" value="Python">
<label for="lang1">파이썬(Python)</label><br>
<input type="checkbox" id="lang2" name="lang2" value="JAVA">
<label for="lang2">자바(JAVA)</label><br>
<input type="checkbox" id="lang3" name="lang3" value="Go">
<label for="lang3">고(Go)</label><br>
date
<label for="birthday">생년월일</label>
<input type="date" id="birthday" name="birthday">
file
<label for="userfiles">파일선택</label>
<input type="file" id="userfiles" name="userfiles" multiple>
submit
<input type="submit" value="전송하기">
form 속성
폼, Form: 사용자가 웹에 입력한 데이터를 서버로 전송하기 위한 방식
<form action="next/" method="post">
<label for="name">이름</label>
<input type="text" id="name" name="name"/>
<label for="email">이메일</label>
<input type="email" id="email" name="email"/>
<label for="birth">생일</label>
<input type="date" id="birth" name="birth"/>
<input type="submit" value="전송">
</form>
클라이언트는 서버에게 요청(Request), 서버는 요청을 받아 처리한 후 응답(Response)
대표적인 Request 두가지:
Form 처리 과정
posts app에 forms.py 생성
#forms.py
from django import forms
class PostForm(forms.Form):
title = forms.CharField(max_length=50, label='제목')
content = forms.CharField(label='내용', widget=forms.Textarea)
views.py에 폼을 이용할 function define하기
#views.py
from posts.forms import PostForm
from django.shortcuts import render
def post_create(request):
post_form = PostForm()
return render(request, 'posts/post_form.html', {'form':post_form})
post_form.html 생성
#post_form.html
<form method="post">{% csrf_token %}
{{form.as_ul}}
<input type="submit" value="전송">
</form>
서버에서 데이터를 받아서 처리하는 과정
#views.py
from django.shortcuts import render,redirect
from posts.models import Post
from posts.forms import PostForm
def post_create(request):
if request.method == "POST":
title = request.POST['title']
content = request.POST['content']
new_post = Post(
title = title,
content = content
)
new_post.save()
return redirect('post-detail', post_id=new_post.id)
else:
post_form = PostForm()
return render(request, 'posts/post_form.html', {'form':post_form})
CSRF, Cross-Site Request Forgery, 크로스 사이트 요청 위조: 웹사이트에서 유저가 서버로 요청을 보내는 행위를 악의적으로 변경해서 요청 전송
위조 방지 토큰 (i.e., csrf_token): 서버로부터 폼을 요청할 때 발행되어 유저가 폼에 데이터를 입력하고 서버로 전송할 때 이 토큰 값을 함께 전달해서 서버에서 토큰 값을 비교한 뒤 요청을 처리하는 방식
<form action="/user" method="post">{% csrf_token %}
...
</form>
# forms.py
from django import forms
class UserForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField(label='Your age')
<!-- html -->
<label for="id_name">Name:</label>
<input type="text" name="name" required id="id_name">
<label for="id_age">Your age:</label>
<input type="number" name="age" required id="id_age">
# forms.py
from django import forms
class UserForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField(label_suffix='=')
<!-- html -->
<label for="id_name">Name:</label>
<input type="text" name="name" required id="id_name">
<label for="id_age">Age=</label>
<input type="number" name="age" required id="id_age">
# forms.py
from django import forms
class UserForm(forms.Form):
name = forms.CharField(help_text='한글 이름을 작성해주세요.')
age = forms.IntegerField()
<!-- html -->
<label for="id_name">Name:</label>
<input type="text" name="name" required id="id_name">
<span class="helptext">한글 이름을 작성해주세요.</span>
<label for="id_age">Age:</label>
<input type="number" name="age" required id="id_age">
웹서비스에서의 폼은 유저에게 데이터 입력을 받아 데이터베이스에 저장하는 경우가 많아서 모델을 기반으로 만드는 경우가 많음
Model Form: 우리가 작성한 모델을 기반으로 폼을 만들어주는 기능
Model Form 작성
#forms.py
from django import forms
from .models import Post #이용할 모델 import
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
View 로직을 모델폼에 맞게 수정
#views.py
from django.shortcuts import render,redirect
from posts.models import Post
from posts.forms import PostForm
def post_create(request):
if request.method == "POST":
post_form = PostForm(request.POST) #유저가 입력하자마자 바인딩
new_post = post_form.save() #데이터베이스에 저장
return redirect('post-detail', post_id=new_post.id)
else:
post_form = PostForm()
return render(request, 'posts/post_form.html', {'form':post_form})
데이터 유효성: 데이터가 우리가 원하는 규격에 맞는지 확인하는 과정
(예) 입력된 데이터 type이 맞는지, 필수 입력칸에 입력했는지, 입력하면 안되는 기호가 들어갔는지 등
유효성 검증, validation:
기본 옵션 인자 사용:
#models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length = 50, unique = True,
error_messages = {'unique':'이미 있는 제목이네요!'})
content = models.TextField()
...
post_create 뷰에 유효성 검증 단계 추가하기
def post_create(request):
if request.method == "POST":
post_form = PostForm(request.POST) #유저가 입력하자마자 바인딩
**if post_form.is_valid():
new_post = post_form.save()
return redirect('post_detail', post_id=new_post.id)**
else:
post_form = PostForm()
return render(request, 'posts/post_form.html', {'form':post_form})
Built-in validator 사용
#models.py
import django.db import models
**from django.core.validators import MinLengthValidator**
class Post(models.Model):
title = models.CharField(max_length = 50, unique = True,
error_messages = {'unique':'이미 있는 제목이네요!'})
content = models.TextField(**validators=[MinLengthValidator(10,
'너무 짧군요! 10자 이상 적어주세요!'**)])
...
직접 Validator 만들기
#validators.py
from django.core.exceptions import ValidationError
def validate_symbols(value):
if ("@" in value) or ("#" in value):
raise ValidationError('"@"와 "#"은 포함될 수 없습니다.', code='symbol-err')
models.py에 내가 만든 validator 사용하기
#models.py
from django.db import models
from django.core.validators import MinLengthValidator
**from .validators import validate_symbols**
# Create your models here.
class Post(models.Model):
#글의 제목, 내용, 작성일, 마지막 수정일
title = models.CharField(max_length=50, unique=True, error_messages={'unique':'이미 있는 제목이네요!'})
content = models.TextField(validators=[MinLengthValidator(10, message='너무 짧군요! 10자 이상 적어주세요!'),
**validate_symbols**])
dt_created = models.DateTimeField(verbose_name="Date Created", auto_now_add = True)
dt_modified = models.DateTimeField(verbose_name = 'Date Modified', auto_now=True)
def __str__(self):
return self.title
views.py에서 데이터가 유효검사를 통과했을 때에만 데이터베이스에 저장하도록 수정
#forms.py
from django import forms
from .models import Post
from .validators import validate_symbols
class PostForm(forms.ModelForm):
**memo = forms.CharField(max_length=80, validators=[validate_symbols])**
class Meta:
model = Post
fields = ['title', 'content']
OR#forms.py
from django import forms
from .models import Post
from .validators import validate_symbols
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
def clean_title(self):
**title = self.cleaned_data['title']
if '*' in title:
raise ValidationError('*는 포함될 수 없습니다.')
return title**
#post_form.html
<form method="post">{% csrf_token %}
<h3>제목</h3>
<p>{{**form.title**}}</p>
{% for error in **form.title.errors** %}
<p>{{error}}</p
{% endfor %}
<h3>내용</h3>
<p>{{**form.content**}}</p>
{% for error in **form.content.errors** %}
<p>{{error}}</p>
{% endfor %}
<input type="submit" value="전송">
</form>
Form에 CSS 적용하기
#form.css
.title {
width: 400px;
}
#forms.py
from django import forms
from .models import Post
from .validators import validate_symbols
from django.core.exceptions import ValidationError
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
**widgets = {'title':forms.TextInput(attrs={
'class':'title',
'placeholder': '제목을 입력하세요.'})
'content': forms.Textarea(attrs={
'placeholder':'내용을 입력하세요.'})}**
def clean_title(self):
title = self.cleaned_data['title']
if '*' in title:
raise ValidationError('*는 포함될 수 없습니다.')
return title
post detail 페이지에 수정하기 버튼 추가
#post_detail.html
...
<div class="btn">
<div class="btn_link"><a href={% url 'post-list' %}>목록으로</a></div>
<div class="right-btn">
<div class="btn_modify">
<a href="{% url 'post-update' post.id %}">수정하기</a>
</div>
</div>
</div>
...
views.py에 post_update 뷰 추가
...
def post_update(request, post_id):
post = Post.objects.get(id=post_id)
if request.method == "POST":
post_form = PostForm(request.POST, instance=post)
if post_form.is_valid():
post_form.save()
return redirect('post-detail', post_id=post.id)
else: #get 방식일때는 사용자가 데이터를 수정할 수 있도록 폼을 생성해서 제공함
#기존 모델의 데이터를 가져와서 채운 상태의 폼 제공
post_form = PostForm(instance=post)
return render(request, 'posts/post_form.html', {'form':post_form})
post detail 페이지에 삭제하기 버튼 추가
post를 삭제할건지 확인하는 페이지 추가
{% extends './base.html' %}
{% load static %}
{% block css %}
<link rel="stylesheet" href="{% static 'posts/css/post_confirm_delete.css' %}">
{% endblock css %}
{% block content %}
<div class="confirm">
<p class="title">[{{post.title}}]</p>
<p>삭제하시겠습니까?</p>
<form method="POST">{% csrf_token %}
<div class="confirm_btn">
<input type="submit" value="삭제하기">
</div>
</form>
</div>
{% endblock content %}
views.py에 post_delete 정의하기
...
def post_delete(request, post_id):
post = Post.objects.get(id=post_id)
if request.method == "POST":
post.delete()
return redirect('post-list')
else:
return render(request, 'posts/post_confirm_delete.html', {'post':post})
views.py에 index뷰 정의하기
def index(request):
return redirect('post-list')
OR
urls.py에서 재설정하기
...
urlpatterns = [
#path('', views.index, name='index'),
path('', views.post_list, name='post-list'),
...
]
from posts.models import Post
Post.objects.all().delete()
post_list.html 수정
{% if posts %}
<div class="post_container">
{% for post in posts %}
<div class="post"><a href={% url 'post-detail' post.id %}>
<h2 class="title">{{post.title}}</h2>
<p class="date">{{post.dt_created}}</p>
<p class="text">{{post.content|slice:':100'}}</p>
</a></div>
{% endfor %}
</div>
{% else %}
<div class="blank">
<p>보여줄 글이 없어요.<br>첫 글을 작성해보면 어떨까요?</p>
</div>
{% endif %}
views.py의 post_detail 뷰를 수정하여 에러 예상 및 대처
#view.py
...
from django.http import Http404
...
def post_detail(request, post_id):
**try: #오류가 날 수도 있는 코드 삽입
post = Post.objects.get(id=post_id)
except Post.DoesNotExist:
raise Http404()**
context = {"post":post}
return render(request, 'posts/post_detail.html', context=context)
OR
#view.py
...
from django.shortcuts import render, redirect, **get_object_or_404
...**
def post_detail(request, post_id):
**post = get_object_or_404(Post, id=post_id)**
context = {"post":post}
return render(request, 'posts/post_detail.html', context=context)
Seeding, 시딩: 사용할 데이터를 데이터베이스에 추가하는 것
#shell
python manage.py loaddata <seed_file>
장고로부터 데이터 하나를 json형식으로 추출해보기
#shell
python manage.py dumpdata posts --indent=2 > posts_data.json
생성된 json 파일 안에서 데이터 늘리기
json 파일을 데이터베이스에 업로드하기
#shell
python manage.py loaddata posts_data.json
대량 시드데이터가 필요할 때 → Django seed
Django seed
settings.py의 INSTALLED_APPS에 django_seed 추가
#settings.py
...
INSTALLED_APPS = [
...
'django_seed',
]
shell에 명령어 입력하여 씨드 생성하기
#shell
python manage.py seed posts --number=50
기존에 저장돼있던 데이터를 다시 유효성 검증에 맞추기
posts app 내에 validate_data.py 파일 생성
모든 포스트 데이터 가져오기
각각의 포스트 데이터를 보면서 내용 유효성 검증하기
(예) 존재하면 안되는 글자가 있다면 해당 글자 제거
데이터 저장하기
from .models import Post
def validate_post():
# 1. 모든 포스트 데이터 가져오기
posts = Post.objects.all()
# 2. 각각의 포스트 데이터를 보면서 내용 유효성 검증하기
for post in posts:
if '&' in post.content:
print(post.id, '번 글에 &가 있습니다.')
# 3. (ex) 존재하면 안되는 글자가 있다면 해당 글자 제거
post.content = post.content.replace('&', '')
# 4. 데이터 저장하기
post.save()
if post.dt_modified < post.dt_created:
print(post.id, '번 글의 수정일이 생성일보다 과거입니다.')
post.save()
shell 입장
python manage.py shell
>>> from posts.validate_data import validate_post
>>> validate_post()
shell 입장
python manage.py shell
장고에서 제공하는 페이지네이터 객체 가져오기
>>> from django.core.paginator import Paginator
데이터베이스에서 포스트 가져오기
>>> from posts.models import Post
>>> posts = Posts.objects.all()
>>> posts.count() #post 수 확인
페이지네이터로 페이지 나누기
>>> posts = Paginator(posts, 6) #6 포스트마다 페이지 나누기
>>> pages.page_range #페이지 수 확인
페이지 function들
>>> page = pages.page(1)
#views.py
...
from Django.core.paginators import Paginator
#views.py
...
def post_list(request):
posts = Post.objects.all()
**paginator = Paginator(posts, 6)
curr_page_number = request.GET.get('page') #요청한 URL의 querystring 가져오기
if curr_page_number is None:
curr_page_number = 1
page = paginator.page(curr_page_number)
return render(request, 'posts/post_list.html', {'page':page})**
request.GET.get('<keyword>')
#post_list.html
...
{% if page.object_list %}
<div class="post_container">
{% for post in page.object_list %}
<div class="post"><a href={% url 'post-detail' post.id %}>
<h2 class="title">{{post.title}}</h2>
<p class="date">{{post.dt_created}}</p>
<p class="text">{{post.content|slice:':100'}}</p>
</a></div>
{% endfor %}
</div>
<div class="paginator">
{% if page.has_previous %}
<a href="?page=1" class="first">first</a>
<a href="?page={{page.previous_page_number}}" class="prev">prev</a>
{% endif %}
<span>
<p>{{page.number}} of {{page.paginator.num_pages}}</p>
</span>
{% if page.has_next %}
<a href="?page={{page.next_page_number}}" class="next">next</a>
<a href="?page={{page.paginator.num_pages}}" class="last">last</a>
{% endif %}
</div>
{% else %}
shell에서는 자동 사용 가능
하지만 code 파일에서는 views.py에서 직접 구현해야 함
class: 변수와 함수의 집합 (예) models.py
클래스형 뷰(Class based view): 개발자들이 자주 쓸만한 view를 클래스로 만들어둔 것
#views.py
...
from django.core.paginator import Paginator
class PostCreateView(View):
def get(self, request):
post_form = PostForm()
return render(request, 'posts/post_form.html', {'form':post_form})
def post(self, request):
post_form = PostForm(request.POST) #유저가 입력하자마자 바인딩
if post_form.is_valid():
new_post = post_form.save()
return redirect('post-detail', post_id=new_post.id)
return render(request, 'posts/post_form.html', {'form':post_form})
...
#urls.py
...
urlpatterns = [
...
path('posts/new', **views.PostCreateView.as_view()**, name='post-create'),
...
]
Generic View: 개발자들이 자주 쓸만한 view를 하나의 형태로 만들어둔 것
views.py에 Django가 제공하는 generic CreateView 가져오기
views.py에 Django가 제공하는 reverse 가져오기
#views.py
...
from django.views.generic import CreateView
from django.urls import reverse
#views.py
...
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'posts/post_form.html' #렌더할 템플릿
#정상적으로 작성이 된 후, 이동할 URL을 제공하는 기능
def get_success_url(self):
return reverse('post-detail', kwargs={'post_id':self.object.id})
A. 포스트 목록 뷰를 제네릭 뷰로 생성하기
#views.py
...
from django.views.generic import CreateView, ListView
#views.py
class PostListView(ListView):
model = Post
template_name = 'posts/post_list.html'
context_object_name = 'posts'
#글 최신순으로 정렬하기
ordering = ['-dt_created']
paginate_by = 6
page_kwarg = 'page' #쿼리스트링에서 찾아야할 키워드
post-list.html 수정
urls.py에서 PostListView.as_view() 로 변경
B. 포스트 디테일 뷰를 제네릭 뷰로 생성하기
#views.py
...
from django.views.generic import CreateView, ListView, DetailView
#views.py
class PostDetailView(DetailView):
model = Post
template_name = 'posts/post_detail.html'
pk_url_kwarg = 'post_id'
context_object_name = 'post'
pk_url_kwarg = <데이터를 조회할 조건(key)>
C. 포스트 수정 뷰를 제네릭 뷰로 생성하기
#views.py
...
from django.views.generic import CreateView, ListView, DetailView, UpdateView
#views.py
class PostUpdateView(UpdateView):
model = Post
form_class = PostForm
template_name = 'posts/post_form.html'
pk_url_kwarg = 'post_id'
def get_success_url(self):
return reverse('post-detail', kwargs={'post_id':self.object.id})
D. 포스트 삭제 뷰를 제네릭 뷰로 생성하기
#views.py
...
from django.views.generic import CreateView, ListView, DetailView, UpdateView, DeleteView
#views.py
class PostDeleteView(DeleteView):
model = Post
template_name = 'posts/post_confirm_delete.html'
pk_url_kwarg = 'post_id'
context_object_name = 'post'
def get_success_url(self):
return reverse('post-list')
View | Template으로 전달되는 데이터 | 예시 |
---|---|---|
ListView | ‘object_list’, ‘<모델명>_list’ | ‘post_list’ |
DetailView | 'object’, ‘<모델명>’ | 'post’ |
CreateView | - | - |
UpdateView | 'object’, ‘<모델명>’ | ‘post’ |
DeleteView | 'object’, ‘<모델명>’ | 'post’ |
context_object_name: view에서 template으로 전달하는 model 데이터에 대한 이름 지정
ListView에서 template으로 전달하는 context
{
'paginator': <Django에서 제공하는 Paginator 객체>, #default으로 None값
'page_obj': <Page 객체>
'is_paginated': False,
'object_list': [데이터 목록이 담겨 있는 QuerySet],
'<모델명>_list': [데이터 목록이 담겨 있는 QuerySet],
}
예시)
A. ListView의 기본값
간단한 코드 버전
class PostListView(ListView):
model = Post
ordering = ['-dt_created']
paginate_by = 6
list view가 pagination을 적용한 데이터의 목록을 object_list라는 키로 템플릿에 전달
B. DetailView의 기본값
class PostDetailView(DetailView):
model = Post
#pk_url_kwarg = 'post_id' **--> urls.py에서 post_id를 pk로 수정하면 삭제 가능**
C. CreateView의 기본값
class PostCreateView(CreateView):
model = Post
form_class = PostForm #'form' 키워드로 접근 가능
def get_success_url(self):
return reverse('post-detail', kwargs={'pk':self.object.id})
D. UpdateView의 기본값
class PostUpdateView(UpdateView):
model = Post
form_class = PostForm
def get_success_url(self):
return reverse('post-detail', kwargs={'pk':self.object.id})
E. UpdateView의 기본값
ReverseView 가져오기
#views.py
...
from django.views.generic import (
CreateView, ListView, DetailView, UpdateView, DeleteView, RedirectView
)
IndexRedirectView 만들기
#views.py
class IndexRedirectView(RedirectView):
pattern_name = 'post-list'
urls.py에서 연결 수정하기
...
urlpatterns = [
path('', views.IndexRedirectView.as_view(), name='index'),
...
]
Base Views
Display Views
Editing Views
Context: View에서 Template으로 전달되어 렌더링시 사용할 수 있는 사전형 데이터 변수
모델(Model) 데이터
참고: 코드잇 장고 강의