728x90

 

 

-- 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 추가

  1. ModelForm을 생성해 자동으로 Model에 결과물을 저장할 수 있다.

  2. Form을 하나 만들어서 Post 모델에 적용한다.

  3. 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 추가

  1. ^은 "시작"을 뜻합니다.

  2. post/new란 URL이 post 문자를 포함해야 한다는 것을 말합니다

  3. /은 다음에/가 한 번 더 와야 한다는 의미입니다.

  4. $는"마지막"을 말합니다.그 뒤로 더는 문자가 오면 안 됩니다.

#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(글 추가) 페이지 링크 추가

  1. blog/templates/blog/base.html 파일을 열어서, page-header 라는 div class에 등록 폼 link를 하나 추가한다.

  2. 새로운 view는 post_new입니다.

  3. 부트스트랩 테마에 있는 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() 함수 추가

  1. 새 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 페이지 추가

  1. {{ form.as_p }}를 HTML 태그로 폼을 감싸세요. <form method="POST">...</form>

  2. <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 저장하기

  1. 새 블로그 글을 작성한 다음에 post_detail 페이지로 이동 합니다.

  2. post_detail은 이동 해야 할 view의 name이고, post_detail view는 pk=post.pk를 사용해서 view에게 값을 넘겨줍니다.

  3. 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 추가

  1. ^은 "시작"을 뜻합니다.

  2. post/1/edit란 URL이 post 문자를 포함 해야 한다는 것을 말합니다

  3. /은 다음에/가 한 번 더 와야 한다는 의미입니다.

  4. $는"마지막"을 말합니다.그 뒤로 더는 문자가 오면 안 됩니다.

#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(글 수정) 페이지 링크 추가

  1. blog/templates/blog/post_detail.html 파읷을 열어서, link를 하나 추가한다.

  2. 새로운 view는 post_edit입니다.

  3. 부트스트랩 테마에 있는 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(글 삭제) 페이지 링크 추가

  1. blog/templates/blog/post_detail.html 파읷을 열어서, link를 하나 추가한다.

  2. 새로운 view는 post_remove입니다.

  3. 부트스트랩 테마에 있는 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 데코레이터

  1. 로그인 사용자만 포스트를 접근 할 수 있도록 post_new, post_edit, post_remove의 View들을 보호하려고 한다면

  2. Django에서 제공하는 django.contrib.auth.decorators 모듈 안의 login_required 데코레이터 를 사용하면 된다.

  3. 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 추가

  1. 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) 로그인 페이지 템플릿 추가

  1. 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 에 설정 추가

  1. 로그인 하면 최상위 index 레벨에서 로그인이 된다.

#mydjango/settings.py

LOGIN_REDIRECT_URL = '/'

 

 

**로그인 여부 체크하기

5) base.html 수정

  1. 인증이 되었을 때는 추가/수정 버튼을 보여주고, 인증이 되지 않았을 때는 로그인 버튼을 보여줌

#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에 수정

  1. 로그인 사용자만 글을 수정, 삭제 할 수 있도록 체크하기

  2. {% 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 수정

  1. “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 추가

  1. 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 속성들

  1. 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

글 목록보기

 

로그인하기
새로운 글 쓰기
글 수정하기
글 삭제하기
새로운 댓글쓰기
글 세부정보

 

728x90

+ Recent posts