MIXIN으로 comment app 구현하는 시간입니다.
python manage.py startapp commentapp


dk dlrj durlafrh Kemfak

from articleapp.models import Article
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.SET_NULL, null=True, related_name='comment')
writer = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='comment')
content = models.TextField(null=False)
created_at = models.DateField(auto_now=True)
from dataclasses import fields
from commentapp.models import Comment
from django.forms import ModelForm
class CommentCreationForm(ModelForm):
class Meta:
model = Comment
fields = ['content']
from commentapp.forms import CommentCreationForm
from commentapp.models import Comment
from django.shortcuts import render
from django.urls import reverse, reverse_lazy
from django.views.generic import CreateView
# Create your views here.
class CommentCreateView(CreateView):
model = Comment
form_class = CommentCreationForm
template_name = 'commenetapp/create.hml'
def get_success_url(self):
return reverse('articleapp:detail', kwargs={'pk':self.object.article.pk})
path('create/', CommentCreateView.as_view(), name='create'),
{% extends 'base.html' %}
{% load django_bootstrap5 %}
{% block content %}
<div style="text-align: center; max-width: 500px; margin: 4rem auto;">
<div class="mb-4">
<h1>Comment Create</h1>
</div>
<form action="{% url 'commentapp:create' %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
<input type="hidden" name="article_pk" value="">
</form>
</div>
{% endblock %}
마찬가지로 create.html을 그대로 베껴오고 h1태그랑 form태그만 좀 바꿔준다.

또한 이런 식으로 hidden 인풋태그를 넣어둔다.

여기서 mixin이 필요해진다.
{% include 'commentapp/create.html' with article=target_article %}

<input type="hidden" name="article_pk" value="{{ article.pk }}"> #이 값은 조작이 가능하다.


이런 모습을 기대하겠지만...
실제로 서버를 켜서 돌려보면...

이런 에러가 발생한다. 아무래도 detailview에는 form이 없기 때문...
그래서 FormMixin을 사용하게 된다.
from django.views.generic.edit import FormMixin

class ArticleDetailView(DetailView, FormMixin):
model = Article
form_class = CommentCreationForm
context_object_name = 'target_article'
template_name = 'articleapp/detail.html'

class CommentCreateView(CreateView):
model = Comment
form_class = CommentCreationForm
template_name = 'commentapp/create.html'
def form_valid(self, form):
temp_comment = form.save(commit=False)
temp_comment.article = Article.objects.get(pk=self.request.POST['article_pk'])
temp_comment.writer = self.request.user
temp_comment.save()
return super().form_valid(form)
def get_success_url(self):
return reverse('articleapp:detail', kwargs={'pk':self.object.article.pk})

{% if user.is_authenticated %}
<input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
{% else %}
<a href="{% url 'accountapp:login %'}?next={{ request.path }}"
class="btn btn-dark rounded-pill col-6 mt-3">
Login
</a>
{% endif %}


<div style="border: 1px solid; text-align: left; padding: 4%; border-radius: 1rem;
border-color: #bbb">
<div>
<strong>
{{ comment.writer.profile.nickname }}
</strong>
   
{{ comment.created_at }}
</div>
<div style="margin : 1rem 0;">
{{ comment.content }}
</div>
</div>

댓글 보이는 것까지는 구현 완료

<div style="border: 1px solid; text-align: left; padding: 4%; border-radius: 1rem;
border-color: #bbb">
<div>
<strong>
{{ comment.writer.profile.nickname }}
</strong>
   
{{ comment.created_at }}
</div>
<div style="margin : 1rem 0;">
{{ comment.content }}
</div>
{% if comment.writer == user %}
<div style="text-align: right;">
<a href="{% url 'commentapp:delete' pk=comment.pk %}"
class="btn btn-danger rounded-pill">
Delete
</a>
</div>
{% endif %}
</div>

path('delete/<int:pk>', CommentDeleteView.as_view(), name='delete'),

from articleapp.models import Article
from commentapp.models import Comment
from django.http import HttpResponseForbidden
def comment_authorized(func):
def decorated(request, *args, **kwargs):
comment = Comment.objects.get(pk=kwargs['pk'])
if not comment.writer == request.user:
return HttpResponseForbidden()
return func(request, *args, **kwargs)
return decorated
@method_decorator(comment_authorized,'get')
@method_decorator(comment_authorized,'post')
class CommentDeleteView(DeleteView):
model=Comment
context_object_name = 'target_comment'
template_name='commentapp/delete.html'
def get_success_url(self):
return reverse('articleapp:detail', kwargs={'pk':self.object.article.pk})