본문 바로가기
개발/Django_python 웹 프레임워크

ModelForm - 댓글 달기

by 자유로운 코끼리 2020. 7. 29.
728x90

댓글도 1:N 관계를 타나내겠죠?

User와도 1:N, 게시물과도 1:N의 형태를 띄겠네요.!

 

1. Comment model

from django.db import models
from django.contrib.auth.models import User


class Blogapp(models.Model):
    user = models.ForeignKey(User,on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    body = models.TextField()

    def __str__(self):
        return self.title

    def summary(self):
        return self.body[:30]    

class Comment(models.Model):
    user = models.ForeignKey(User,on_delete=models.CASCADE) 
    post = models.ForeignKey(Blogapp,on_delete=models.CASCADE) 
    content = models.TextField(blank = True)
    anonymous = models.BooleanField(default=False)
	created_at = models.DateTimeField(auto_now_add= True)
    updated_at = models.DateTimeField(auto_now = True)

Comment class를 추가해줍니다.

우선 user와 blog를 comment에 1:N 관계로 만들어줬습니다.

1:N 관계 혹은 ForeignKey에 대한 개념이 기억이 나지 않으신다면, 다음 블로그를 참고해주세요.

 

그리고 comtent를 만들어줬는데 blank=True라는 속성은 안에 값이 필수값은 아니라는 것입니다.

데이터베이스에는 ''이 저장됩니다.

 

anonymous는 익명인지 아닌지 체크하게 될 변수로,  Boolenfield를 이용할 것입니다.

Boolenfield는 true/false 필드로, Null 을 허용하기 위해서는 NullBooleanField를 사용합니다.

 

이때 DateTimeField에서 auto_now_add와 auto_now의 속성에 대해서 아셔야합니다.

auto_now_add는 쟝고 모델이 최초 저장시에만 해당 날짜를 저장합니다.

auto_now는 save 될 때마다 현재날짜로 저장합니다.

 

2. admin

# admin.py
from django.contrib import admin
from .models import Post,Comment

admin.site.register(Post)
admin.site.register(Comment)

3. 모델 migrate

python manage.py makemigrations
python manage.py migrate

4. forms.py

#forms.py
from django import forms
from .models import Blogapp,Comment

class BlogPost(forms.ModelForm):
    class Meta:
        model = Blogapp # 어떤 모델을 기반으로 한 입력공간이니?
        fields = ['title','body'] # 그 모델 중에서 어떤 항목을 입력받을거니?

    def __init__(self,*args,**kwargs): 
        #*args : 복수의 인자를 받고자 할 때, *뒤 변수명을 적으면 된다. 
        #**kwargs : 여러 키워드 파라미터를 받을 수 있다(ex- x=10 과 같은!).   
        super().__init__(*args,**kwargs)
        #super()을 이용해 부모클래스의 내용을 가지고 올 수 있다. -오버라이딩 => 즉 Blogapp 내용을 가지고 올 수 있다는 의미죵!
        self.fields['title'].label="제목"
        self.fields['body'].label="본문"
        self.fields['title'].widget.attrs.update({
            'class' : 'title_class',
            'placeholder':'제목을 입력하세요',
        })

class BlogComment(forms.ModelForm):
    class Meta:
        model = Comment # 어떤 모델을 기반으로 한 입력공간이니?
        fields = ['content','anonymous'] # 그 모델 중에서 어떤 항목을 입력받을거니?

BlogComment 클래스를 만들어줍니다.

 

4. views.py 

from .models import Post,Comment
from .forms import BlogPost,BlogComment
def c_create(request,blog_id): # comment create : 댓글 생성&저장 함수
    if request.method == "POST":
        comment = BlogComment(request.POST)
        if comment.is_valid():
            comment_p = comment.save(commit=False)
            comment_p.user = request.user
            comment_p.post = Blogapp.objects.get(id=blog_id) 
            comment_p.save()
            return redirect('/blog/detail/' + str(blog_id)) 

 

5. detail.html 

{% if user.is_authenticated %}
<form action="{% url 'c_create' blog.id%}" method="POST">
    {%csrf_token%}
    <div>
        {{comment_form}}
        <input type="submit" value="제출하기">
</form>
{% endif %}

유저가 로그인되어 있는 상태에서 댓글 버튼이 보이도록 설정하였습니다.

{%for comment in blog.comment_set.all%}
{%if comment.anonymous == True%}
<span>익명</span>
{%else%}
<span>{{comment.user}}</span>
{%endif%}
:{{comment.content}}

<br>
{%endfor%}

1의 입장에서는 관계되어 있는 객체가 많기 때문에 set 을 통해서 접근하여,

blog에 속해있는 comment에 접근하는데 .all을 이용해서 다 다져오게 됩니다.

 

그리고 하나씩 들어가서 출력하게 됩니다.

 

이때 comment.anonynous가 true면, 익명을 체크한 것이기 때문에

username 대신에 익명이 보이게 됩니다.

 

 

6. urls.py 

#urls.py
path('c_create/<int:post_id>',...,name='c_create'),

 

삭제 

#views.py

def delete_comment(request,blog_id,comment_id):
    comment_d=Comment.objects.get(id=comment_id) 
    comment_d.delete()
    return redirect('/blog/detail/' + str(blog_id))
#detail.html
{%if request.user == comment.user or request.user.is_staff %}
<a href="{% url 'delete_comment' blog.id comment.id %}">삭제하기</a>
{%endif%}
<br>
{%endfor%}
path('blog/delete_comment/<int:blog_id>/<int:comment_id>',blogapp.views.delete_comment,name="delete_comment"),

댓글