-- blog App 작성 : Django Form (글 추가)
**Django의 Architecture : Form

**Django Form
1) Form이란?
-
Model클래스와 유사하게 Form클래스를 정의
-
주요 역할 : 커스텀 Form클래스를 통해
-
입력 폼 HTML 생성 : .as_table(), .as_p(), .as_ul() 기본제공
-
입력 폼 값 검증(validation) 및 값 변화 => 서버사이드 측에서(클라이언트 js는 코드가 다 드러나있음)
2) Form 처리 : HTTP Method에 따라
-
폼 처리 시에 같은 URL(즉 같은 뷰)에서 GET/POST로 나눠 처리
-
GET방식으로 요청 : 입력 폼을 보여줍니다.
-
POST방식으로 요청 : 데이터를 입력 받아 유효성 검증 과정을 거칩니다.
검증 성공 시 : 해당 데이터를 저장하고 SUCCESS URL로 이동
검증 실패 시:오류 메시지와 함께 입력 폼을 다시 보여줍니다.

1)step1: Form 클래스 정의
from django import forms
class PostForm(forms.Form):
title = forms.CharField()
text = forms.CharField(widget=forms.Textarea)
2)step2: 필드 유효성 검사 함수 추가 적용
from django import forms
def min_length_3_validator(value):
if len(value) < 3:
raise forms.ValidationError('3글자 이상 입력해주세요.')
from django import forms
class PostForm(forms.Form):
title = forms.CharField(validators=[min_length_3_validator])
text = forms.CharField(widget=form.Textarea)
3)step3: View 함수 내에서 Form 인스턴스 생성
GET요청을 통해 View 함수가 호출이 될 때, GET/POST 요청을 구분해서 Form 인스턴스 생성
# myapp/views.py
from .forms import PostForm
if request.method == 'POST':
# POST 요청일 때
form = PostForm(request.POST, request.FILES)
else:
# GET 요청일 때
form = PostForm()
4)step4: POST요청에 한해 입력 값 유효성 검증
# myapp/views.py
if request.method == 'POST':
# POST인자는 request.POST와 request.FILES를 제공받음.
form = PostForm(request.POST, request.FILES)
#인자로 받은 값에 대해서,유효성 검증 수행
if form.is_valid(): # 검증이 성공하면, True 리턴
# 검증에 성공한 값들을 dict타입으로 제공받아서 이 값을 DB에 저장하기
form.cleaned_data
post = Post(**form.cleaned_data) # DB에 저장하기
post.save()
return redirect('/success_url/')
else: # 검증에 실패하면, form.errors와 form.각필드.errors 에 오류정보를 저장
form.errors
else:
form = PostForm()
return render(request, 'myapp/form.html', {'form': form})
5)step5: 템플릿을 통해 HTML폼 생성
유효성 검증에서 실패했을 때 Form 인스턴스를 통해 HTML폼 출력하고,오류 메시지도 있다면 같이 출력
<table>
<form action="" method="post">
{% csrf_token %}
<table>{{ form.as_table }}</table>
<input type="submit" />
</form>
</table>
**Django ModelForm 클래스
1) Model Form이란?
-
지정된 Model로부터 필드 정보를 인어 들여, form fields 를 세팅
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = '__all__' # 전체필드지정 혹은 list로 인어올 필드명 지정
-
내부적으로 model instance를 유지
-
유효성 검증에 통과한 값들로, 지정 model instance로의 저장 (save)을 지원 (Create or Update)
**Django Form vs ModelForm
from django import forms
from .models import Post
class PostForm(forms.Form):
title = forms.CharField()
text = forms.CharField(widget=forms.Textarea)
# 생성되는 Form Field는 PostForm과 거의 동일
class PostModelForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'text']
**Post New(글추가)페이지작성하기
1) forms.py 추가
-
ModelForm을 생성해 자동으로 Model에 결과물을 저장할 수 있다.
-
Form을 하나 만들어서 Post 모델에 적용한다.
-
blog 디렉토리 안에 forms.py라는 파일을 작성한다.
forms.ModelForm은 django에 이 폼이 ModelForm이라는 것을 알려주는 구문이다.
class Meta 구문은 Form을 만들기 위해서 어떤 model이 쓰여야 하는지 django에 알려주는 구문 이 폼에 필드는 title과 text만 보여지게 된다. author는 로그인 하고 있는 사람이고, created_date는 글이 등록되는 시간이다.
# blog/forms.py
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'text',)
2) urls.py에 Post New(글 추가) url 추가
-
^은 "시작"을 뜻합니다.
-
post/new란 URL이 post 문자를 포함해야 한다는 것을 말합니다
-
/은 다음에/가 한 번 더 와야 한다는 의미입니다.
-
$는"마지막"을 말합니다.그 뒤로 더는 문자가 오면 안 됩니다.
#blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
]
3) base.html에 Post New(글 추가) 페이지 링크 추가
-
blog/templates/blog/base.html 파일을 열어서, page-header 라는 div class에 등록 폼 link를 하나 추가한다.
-
새로운 view는 post_new입니다.
-
부트스트랩 테마에 있는 glyphicon glyphicon-plus 클래스로 더하기 기호가 보이게 됩니다.
http://bootstrapk.com/components
콤포넌트 · 부트스트랩
Some default panel content here. Nulla vitae elit libero, a pharetra augue. Aenean lacinia bibendum nulla sed consectetur. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam id dolor id nibh ultricies vehicula ut id elit.
bootstrapk.com
#blog/templates/blog/base.html
<div class="page-header">
<a href="{% url 'post_new' %}" class="top-menu">
<span class="glyphicon glyphicon-plus"></span></a>
<h1><a href="/">Django's Blog</a></h1>
</div>
4) views.py에 post_new() 함수 추가
-
새 Post 폼을 추가하기 위해 PostForm() 함수를 호출하도록 하여 템플릿에 넘깁니다.
#blog/views.py
from .forms import PostForm
def post_new(request):
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
5) post_edit.html 페이지 추가
-
{{ form.as_p }}를 HTML 태그로 폼을 감싸세요. <form method="POST">...</form>
-
<form ...>을 열어 {% csrf_token %}를 추가하세요. 이 작업은 폼 보안을 위해 중요합니다. HTML Form의 POST요청에서 CSRF 토큰을 체크하며, 이때 CSRF토큰이 필요합니다. csrf_token tag를 통해 CSRF 토큰을 발급 받을 수 있습니다.
#blog/templates/blog/post_edit.html
{% extends 'blog/base.html' %}
{% block content %}
<h1>New post</h1>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock %}
6-1) Form 저장하기
등록 Form의 두 가지 상황
첫번째:처음 페이지에 접속 했을 때,새 글을 쓸 수 있게Form이 비어 있습니다. 이때의 Http method는 GET
두번째 : Form에 입력된 데이터를 view 페이지로 가지고 올 때입니다. 이때의 Http method는 POST
#blog/views.py
from .forms import PostForm
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
6-2) Form 저장하기
폼에 들어있는 값들이 올바른 지를 확읶하기 위해 form.is_valid()을 사용합니다.
작업을 두 단계로 나눈다.
첫번째 : form.save()로 폼을 저장하는 작업, commit=False란 데이터를 바로 Post 모델에 저장하지 않는다는 뜻입니다.
두번째 : author와 published_date를 추가하는 작업, post.save()는 변경사항을 유지하고 새 블로그 글이 만들어 집니다.
#blog/views.py
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
6-3) Form 저장하기
-
새 블로그 글을 작성한 다음에 post_detail 페이지로 이동 합니다.
-
post_detail은 이동 해야 할 view의 name이고, post_detail view는 pk=post.pk를 사용해서 view에게 값을 넘겨줍니다.
-
post는 새로 생성한 블로그 글입니다.
#blog/views.py
from django.shortcuts import redirect
return redirect('post_detail', pk=post.pk)
6-4) 완성된 post_new 함수
#blog/views.py
from django.shortcuts import redirect
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
-->model이 추가되면 migration에 반영해줘야 함
python manage.py makemigrations blog
python manage.py migrate blog
--blog App 작성 : Django Form (글 수정)
**PostEdit(글수정) 페이지작성하기
1) urls.py에 Post Edit(글 수정) url 추가
-
^은 "시작"을 뜻합니다.
-
post/1/edit란 URL이 post 문자를 포함 해야 한다는 것을 말합니다
-
/은 다음에/가 한 번 더 와야 한다는 의미입니다.
-
$는"마지막"을 말합니다.그 뒤로 더는 문자가 오면 안 됩니다.
#blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
]
2) post_detail.html에 Post Edit(글 수정) 페이지 링크 추가
-
blog/templates/blog/post_detail.html 파읷을 열어서, link를 하나 추가한다.
-
새로운 view는 post_edit입니다.
-
부트스트랩 테마에 있는 glyphicon glyphicon-pencil 클래스로 보이게 됩니다.
#blog/templates/blog/post_detail.html
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% endif %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
<span class="glyphicon glyphicon-pencil"></span></a>
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
3) views.py에 post_edit() 함수 추가
작업을 두 단계로 나눈다.
첫 번째: url로부터 추가로 pk 매개변수를 받아서 처리합니다.
두 번째: get_object_or_404(Post, pk=pk)를 호출하여 수정하고자 하는 글의 Post 모델 인스턴스(instance)로 가져온 데이터를 폼을 만들 때와 폼을 저장할 때 사용하게 됩니다.
#blog/views.py
@login_required
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
--blog App 작성 : Django Form (글 삭제)
**Post remove ( 글 삭제 ) 페이지 작성하기
1) urls.py에 Post remove(글 삭제) url 추가
#blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
path('post/<int:pk>/remove/', views.post_remove, name='post_remove'),
]
2) post_detail.html에 Post Remove(글 삭제) 페이지 링크 추가
-
blog/templates/blog/post_detail.html 파읷을 열어서, link를 하나 추가한다.
-
새로운 view는 post_remove입니다.
-
부트스트랩 테마에 있는 glyphicon glyphicon-remove 클래스로 보이게 됩니다.
#blog/templates/blog/post_detail.html
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% endif %}
<a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}">
<span class="glyphicon glyphicon-remove"></span></a>
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
3) views.py에 post_remove() 함수 추가
작업을 두 단계로 나눈다.
첫 번째: url로부터 추가로 pk 매개변수를 받아서 처리 합니다.
두 번째: get_object_or_404(Post, pk=pk)를 호출하여 삭제 하고자 하는 글의 Post 모델 인스턴스(instance)로 가져 와서 삭제 처리를 한다.
#blog/views.py
@login_required
def post_remove(request, pk):
post = get_object_or_404(Post, pk=pk)
post.delete()
return redirect('post_list')
java vs python
redirect -> redirect
forward -> render
* render 는 템플릿을 불러오고, redirect 는 URL로 이동합니다.
URL 로 이동한다는 건 그 URL 에 맞는 views 가 다시 실행될테고 여기서 render 를 할지 다시 redirect 할지 결정할 것 입니다.
--blog App 작성 : 로그인/로그아웃 처리하기
**로그인 처리하기
1) @login_required 데코레이터
-
로그인 사용자만 포스트를 접근 할 수 있도록 post_new, post_edit, post_remove의 View들을 보호하려고 한다면
-
Django에서 제공하는 django.contrib.auth.decorators 모듈 안의 login_required 데코레이터 를 사용하면 된다.
-
login_required 데코레이터는 로그읶 페이지로 리다이렉션(Redirection) 된다.
* 주의: 로그인 되어 있는 admin 페이지를 로그아웃 해야 함
* https://docs.djangoproject.com/en/2.0/topics/auth/default/#auth-web-requests
Using the Django authentication system | Django documentation | Django
Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate
docs.djangoproject.com
#blog/views.py
from django.contrib.auth.decorators import login_required
@login_required
def post_new(request):
[...]
2) urls.py 에 login url 추가
-
blog/urls.py가 아니라 myjango/urls.py에 로그인 url 추가
#mydjango/urls.py
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
path('accounts/login/', auth_views.LoginView.as_view(template_name="registration/login.html"),
name="login"),
]
3) 로그인 페이지 템플릿 추가
-
blog/templates/registration 디렉토리를 생성하고, login.html 파일 작성
#blog/templates/registration/login.html
{% extends "blog/base.html" %}
{% block content %}
{% if form.errors %}
<p>이름과 비밀번호가 일치하지 않습니다. 다시 시도해주세요.</p>
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table class="table table-bordered table-hover">
<tr>
<td>{{ form.username.label_tag }}</td><td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td><td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="login" class="btn btn-primary btn-lg" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{% endblock %}
4) settings.py 에 설정 추가
-
로그인 하면 최상위 index 레벨에서 로그인이 된다.
#mydjango/settings.py
LOGIN_REDIRECT_URL = '/'
**로그인 여부 체크하기
5) base.html 수정
-
인증이 되었을 때는 추가/수정 버튼을 보여주고, 인증이 되지 않았을 때는 로그인 버튼을 보여줌
#blog/templates/blog/base.html
<div class="page-header">
{% if user.is_authenticated %}
<a href="{% url 'post_new' %}" class="top-menu">
<span class="glyphicon glyphicon-plus"></span></a>
{% else %}
<a href="{% url 'login' %}" class="top-menu">
<span class="glyphicon glyphicon-lock"></span></a>
{% endif %}
<h1><a href="/">Django's Blog</a></h1>
</div>
6) post_detail.html에 수정
-
로그인 사용자만 글을 수정, 삭제 할 수 있도록 체크하기
-
{% if %} 태그를 추가해 관리자로 로그인한 사용자들만 글 수정,삭제 링크가 보일 수 있게 맊든다.
#blog/templates/blog/post_detail.html
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
<span class="glyphicon glyphicon-pencil"></span></a>
<a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}">
<span class="glyphicon glyphicon-remove"></span></a>
{% endif %}
**로그아웃 처리하기
1) base.html 수정
-
“Hello <사용자이름>” 구문을 추가하여 읶증된 사용자라는 것을 알려주고, logout link를 추가함
#blog/templates/blog/base.html
<div class="page-header">
{% if user.is_authenticated %}
<a href="{% url 'post_new' %}" class="top-menu">
<span class="glyphicon glyphicon-plus"></span></a>
<p class="top-menu">Hello {{ user.username }}<small>(<a href="{% url 'logout' %}?next={{request.path}}">Log out</a>)</small></p>
{% else %}
<a href="{% url 'login' %}" class="top-menu">
<span class="glyphicon glyphicon-lock"></span></a>
{% endif %}
<h1><a href="/">Django's Blog</a></h1>
</div>
2) urls.py 에 logout url 추가
-
blog/urls.py가 아니라 myjango/url.py에 로그아웃 url 추가
#mydjango/urls.py
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
path('accounts/login/', auth_views.LoginView.as_view(template_name="registration/login.html"), name="login"),
path('accounts/logout/', auth_views.LogoutView.as_view(), {'next': None}, name='logout'),
]
--blog App 작성 : 댓글 모델(comment model) 작성
**댓글(Comment) 작성 – Comment Model 속성들
-
Comment(댓글)의 속성들
- post(Post Model를 참조하는 Foreign Key)
- author(글쓴이)
- text(내용)
- created_date(작성일)
- approved_comment(승인여부)
2. Comment 객체는 blog/models.py 파일에 선언하여 모델을 만듭니다. blog/models.py 파일을 열고, Comment class의 내용을 추가해 주세요.
**댓글(Comment) 작성 – Comment Class 작성 2) models.py 에 Comment class 추가
#blog/models.py
from django.db import models
from django.utils import timezone
class Comment(models.Model):
post = models.ForeignKey('blog.Post',on_delete=models.CASCADE,related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.text
**댓글(Comment)작성– 테이블생성및관리자패널에등록
3) 마이그레이션 파읷(migration file) 생성하기
django_src> python manage.py makemigrations blog
4) 실제 데이터베이스에 Post, Comment Model 클래스를 반영하기
django_src> python manage.py migrate blog
5) 관리자 페이지에서 만든 모델을 보기 위해 Comment 모델을 등록
blog/admin.py에 아래 코드를 추가
#blog/admin.py
from django.contrib import admin
from .models import Post,Comment
admin.site.register(Post)
admin.site.register(Comment)
**댓글(Comment) 작성 – 관리자 화면에서 확인
6) 관리자 화면에서 확인하기 http://localhost:8000/admin/ 으로 접속
**QuerySet 연습해보기
python manage.py shell
from blog.models import Post, Comment
posts = Post.objects.all()
type(posts)
>>>django.db.models.query.QuerySet
for post in posts:
...: print(post.id, post.title)
>>>1 첫번째글
2 두번째글
4 세번째글
5 네번째글
6 몽구는
post6 = Post.objects.get(id=6)
post6.comments
>>><django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager<locals>.RelatedManager at 0x7f8c06df63d0>
post6.comments.all()
>>><QuerySet [<Comment: 몽글이 살이빠졌습니다.>, <Comment: 3.66kg인데 3.5kg까지 빼는 것이 목표입니다
comments = post6.comments.all()
for comment in comments:
...: print(comment.id, comment.author, comment.text, comment.post)
>>>1 몽글주인 몽글이 살이빠졌습니다. 몽구는
2 몽글아빠 3.66kg인데 3.5kg까지 빼는 것이 목표입니다. 몽구는
for comment in comments:
...: print(comment.id, comment.author, comment.post.id)
>>>1 몽글주인 6
2 몽글아빠 6
post6.comments.count()
>>>2
**댓글(Comment) 작성- Comment를 화면에 나타내기
7) blog/templates/blog/post_detail.html 수정
Comment를 화면에 나타나게 하기 위해 {% endblock %} tag 전에 아래 코드를 추가
#blog/templates/blog/post_detail.html
<hr>
{% for comment in post.comments.all %}
<div class="comment">
<div class="date">{{ comment.created_date }}</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
**댓글(Comment) 작성- Comment를 화면에 나타내기
8) blog/css/blog.css 수정
아래의 css 코드 추가하기
#blog/css/blog.css
.comment {
margin: 20px 0px 20px 20px;
}
9) blog/templates/blog/post_list.html 수정
Post list 페이지에서 각 post 별 댓글 갯수를 출력하기: 아래의 링크 추가
#blog/templates/blog/post_list.html
<a href="{% url 'post_detail' pk=post.pk %}">Comments:{{ post.comments.count }}</a>
**댓글(Comment) 작성- Comment를 등록하기
10) blog/forms.py 수정 – Comment form 추가
blog/forms.py 파일 끝에 아래 코드를 추가하기
#blog/forms.py
from .models import Post, Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
11) blog/urls.py 수정 – Comment 등록 url 추가
#blog/urls.py
from django.urls import path
path('post/<int:pk>/comment/', views.add_comment_to_post, name='add_comment_to_post'),
12) blog/views.py 수정 – add_comment_to_post() 함수 추가
#blog/views.py
from .forms import PostForm, CommentForm
def add_comment_to_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/add_comment_to_post.html', {'form': form})
13) blog/templates/blog/post_detail.html 수정 – Comment 등록 link 추가
{% for comment in post.comments.all %} 전에 아래 코드를 추가
#blog/templates/blog/post_detail.html
<a class="btn btn-default" href="{% url 'add_comment_to_post' pk=post.pk %}">Add comment</a>
post detail 페이지에서, "Add Comment" 버튼을 확인할 수 있습니다.
14) blog/templates/blog/add_comment_to_post.html 추가
:Comment 등록 할 수 있는 템플릿 추가
#blog/templates/blog/add_comment_to_post.html
{% extends 'blog/base.html' %}
{% block content %}
<table>
<h1>New comment</h1>
<form method="POST" class="post-form">{% csrf_token %}
<table class="table table-bordered table-hover">
{{ form.as_table }}
</table>
<button type="submit" class="save btn btn-default">Send</button>
</form>
</table>
{% endblock %}
**댓글(Comment) 관리 – 댓글 승인 , 삭제 하기
1) 블로그 관리자가 댓글을 승인하거나 삭제할 수 있는 기능
post detail 페이지에 댓글 삭제, 승인 버튼을 추가합니다.
#blog/templates/blog/post_detail.html
{% for comment in post.comments.all %}
{% if user.is_authenticated or comment.approved_comment %}
<div class="comment">
<div class="date">
{{ comment.created_date }}
{% if not comment.approved_comment %}
<a class="btn btn-default" href="{% url 'comment_remove' pk=comment.pk %}">
<span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-default" href="{% url 'comment_approve' pk=comment.pk %}">
<span class="glyphicon glyphicon-ok"></span></a>
{% endif %}
</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% endif %}
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
2) blog/urls.py 수정 – Comment 승인, 삭제 url 추가
#blog/urls.py
path('comment/<int:pk>/approve/', views.comment_approve, name='comment_approve'),
path('comment/<int:pk>/remove/', views.comment_remove, name='comment_remove'),
3) blog/views.py 수정 – comment_approve(),comment_remove() 함수 추가
#blog/views.py
@login_required
def comment_approve(request, pk):
comment = get_object_or_404(Comment, pk=pk)
comment.approve()
return redirect('post_detail', pk=comment.post.pk)
@login_required
def comment_remove(request, pk):
comment = get_object_or_404(Comment, pk=pk)
post_pk = comment.post.pk
comment.delete()
return redirect('post_detail', pk=post_pk)
4) blog/templates/blog/post_list.html 수정
등록된 모든 댓글의 갯수가 대신에 승인된 댓글의 갯수가 노출 되도록 수정
#blog/templates/blog/post_list.html
<a href="{% url 'blog.views.post_detail' pk=post.pk %}">Comments: {{ post.comments.count }}</a>
#blog/templates/blog/post_list.html
<a href="{% url 'blog.views.post_detail' pk=post.pk %}">Comments: {{ post.approved_comments.count }}</a>
5) blog/models.py 수정
Post 모델에 approved_comments 메서드를 추가
#blog/models.py
def approved_comments(self):
return self.comments.filter(approved_comment=True)
>>shell
from blog.models import Post, Comment
In [3]: posts = Post.objects.all()
In [4]: for post in posts:
...: print(post.pk, post.comments.count())
>>>1 0
2 2
4 0
5 0
6 3
post6.comments.count()
>>>3
post6.approved_comments().count()
>>>3







'CLOUD > Django' 카테고리의 다른 글
1/21 Django - 복습 2차시(with VS Code) (0) | 2021.01.21 |
---|---|
1/20 - Django 복습(with VS Code) (0) | 2021.01.20 |
1/15 Django 4차시 - blog app 만들기(Maria DB, 페이징처리, django REST frame) (0) | 2021.01.15 |
1/13 Django 2차시 - blog app만들기(list, detail), css, bootstrap (0) | 2021.01.13 |
1/12 Django 1차시 - blog만들기 (0) | 2021.01.12 |