본문 바로가기
기타/django

작정하고 장고 - commentapp 만들기

by 방배킹 2023. 5. 31.

commentapp 만들기

  1. python manage.py startapp commentapp 명령어을 통해 commentapp을 만든다.
  2. main project의 urls.py와 settings.py에 설정을 해준다.
  3. commentapp에 urls.py를 만들고 commentapp을 만들어준다.
#1
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bootstrap4',
    'accountapp',
    'profileapp',
    'articleapp',
    #commentapp 추가
    'commentapp',
]
#2
urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('accountapp.urls')),
    path('profiles/', include('profileapp.urls')),
    path('articles/', include('articleapp.urls')),
    #comments 추가
    path('comments/', include('commenteapp.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
#3
app_name = 'commentapp'
urlpatterns = [

]

commentapp의 model과 form을 만들어준다.

#models.py
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.DateTimeField(auto_now=True)
    
#forms.py
class CommentCreationForm(ModelForm):
    class Meta:
        model = Comment
        fields = ['content']

DB에 저장한다.
1. python manage.py makemigrations
2. python manage.py migrate

views.py에서 CreateView를 만들자.

#CreateView 생성
class CommentCreateView(CreateView):
    model = Comment
    form_class = CommentCreationForm
    template_name = 'commentapp/create.html'

    def get_success_url(self):
        return reverse('articleapp:detail', kwargs={'pk' : self.object.article.pk})

commentapp/templates/commentapp/create.html을 만들고

{% load bootstrap4 %}

{% block content %}

  <div style="text-align: center; max-width: 500px; margin: 4rem auto">
    <div class="mb-4">
      <h4>Comment Create</h4>
    </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="{{ article.pk }}">
    </form>
  </div>

{% endblock %}

articleapp/templates/articleapp/detail.html에 include 해준다.

{% include 'commentapp/create.html' with article=target.article %}


comments/create은 잘 접속이 되지만


article에 들어가서 확인을 하려고 하면 form이 없다는 오류가 발생한다.
(form mixin이 필요)

# FormMixin과 form_class = CommentCreationForm를 추가해준다.
class ArticleDetailView(DetailView, FormMixin):
    model = Article
    form_class = CommentCreationForm
    context_object_name = 'target_article'
    template_name = 'articleapp/detail.html'


잘 작동이 된다.

로그인이 되었을때 댓글을 달수 있도록 create.html에 코드 추가

{% load bootstrap4 %}

{% block content %}

  <div style="text-align: center; max-width: 500px; margin: 4rem auto">
    <div class="mb-4">
      <h4>Comment Create</h4>
    </div>
    <form action="{% url 'commentapp:create' %}" method="post">
      {% csrf_token %}
      {% bootstrap_form form %}
      
<!-- 추가내용 -->
      
      {% 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 %}
      
<!-- 추가내용 -->
      
      <input type="hidden" name="article_pk" value="{{ article.pk }}">
    </form>
  </div>

{% endblock %}

articleapp의 detail.html에 해당 코드를 추가해서 comment가 보이도록 해준다.

{% for comment in target_article.comment.all %}
      {% include 'commentapp/detail.html' with comment=comment %}
{% endfor %}

위 코드에서 commentapp/detail.html는 아래와 같다.

<div style="border: 1px solid; text-align:left; padding: 4%; margin: 1rem 0; border-radius: 1rem;
border-color:#bbb;" >
  <div>
    <strong>
      {{ comment.writer.profile.nickname }}
    </strong>
    &nbsp&nbsp&nbsp
    {{ comment.create_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>

댓글을 쓴사람의 닉네임과 작성 날짜, 내용을 보여주고,
{% if comment.writer == user %} (댓글을 작성한 사람이 현재 user이면) 삭제 버튼도 만들어준다.

{% extends 'base.html' %}

{% block content %}

    <div style = "text-align : center; max-width : 500px; margin: 4rem auto">
        <div class="mb-4">
            <h4>Delete Comment : {{target_comment.content}}</h4>
        </div>
        <form action="{% url 'commentapp:delete' pk=target_comment.pk %}" method = "post">
            {% csrf_token %}
            <input type="submit" class = "btn btn-danger rounded-pill col-6 mt-3 ">
        </form>
    </div>

{% endblock %}

delete.html은 다음과 같다.

@method_decorator(comment_ownership_required, 'get')
@method_decorator(comment_ownership_required, '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})

decorator는 다른 app의 view와 동일하다.

 

 

잘 작동한다.

댓글