본문 바로가기
  • 살짝 구운 김 유나
Web/Django

실습 - 1:N 을 활용한 app 작성

by yunae 2022. 10. 6.

1. Question. Comment 테이블 정보

eithers/models.py

from django.db import models

# Create your models here.
class Question(models.Model):
    title = models.CharField(max_length=200)
    issue_a = models.CharField(max_length=100)
    issue_b = models.CharField(max_length=100)

class Comment(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    pick = models.BooleanField()
    content = models.CharField(max_length=100)

 

2. 각 기능에 맞는 url 설정

either/urls.py

from django.urls import path
from . import views

app_name = 'eithers'
urlpatterns = [
    path('', views.index, name='index'),
    path('create/', views.create, name='create'),
    path('<int:pk>/', views.detail, name='detail'),
    path('random/', views.random_q, name= 'random_q'),
    path('<int:pk>/comments/', views.comments_create, name='comments_create'),
    path('<int:pk>/update/', views.update, name='update'),
    path('<int:pk>/delete/', views.delete, name='delete'),
    path('<int:question_pk>/comment/<int:comment_pk>/delete/', views.comments_delete, name='comments_delete'),
]

 

글을 생성

forms.py

class QuestionForm(forms.ModelForm):
    issue_a = forms.CharField(label="RED TEAM")
    issue_b = forms.CharField(label="BLUE TEAM")

    class Meta:
        model = Question
        fields = '__all__'
        # exclude = ('user',)

-> 선택지 두 개를 저장하는 RED TEAM, BLUE TEAM 이라는 이름으로 값 입력받기 위한 Form 작성

 

 

랜덤하게 글 보여주기

eithers/views.py

import random

def detail(request, pk):
    question = Question.objects.get(pk=pk)
    comment_form = CommentForm()
    comments = question.comment_set.all()
    context = {
        'question' : question,
        'comment_form' : comment_form,
        'comments' : comments,
    }
    return render(request, 'eithers/detail.html', context)


def random_q(request):
    # 전체를 조회한 후에
    questions = list(Question.objects.all())
    # 랜덤으로 하나만 추출해서 (리스트 형태로 추출되기 때문에 [0] 인덱싱)
    question = random.sample(questions, 1)[0]
    # detail 페이지로 리다이렉트
    return redirect('eithers:detail', question.pk)

 

 

detail 페이지에서 글의 정보와 댓글을 작성할 수 있는 창

요구사항 : 댓글 입력창 하단에는 입력된 댓글이 택한 팀 - 댓글 형태

eithers/models.py

class Comment(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    pick = models.BooleanField()
    content = models.CharField(max_length=100)

eithers/forms.py

TEAMS = (
    # 디비에 저장될 내용 / 보여지는 내용
    (False, 'Red'), 
    (True, 'Blue'),
)

class CommentForm(forms.ModelForm):

    pick = forms.ChoiceField(choices=TEAMS)   

    class Meta:
        model = Comment
        # fields = '__all__'
        exclude = ('question',)

-> pick은 bool 타입이기 때문에 form에서 재정의 해주기

 

detail.html

<b>댓글 목록</b>
  <br>
  <ul>
    {% for comment in comments %}
      {% if comment.pick == False %}
        <p>Red - {{ comment.content }}</p> 
      {% else %}
        <p>Blue - {{ comment.content }}</p> 
      {% endif %}

    {% endfor %}

-> choice를 사용해도 보여지는 내용이 대체되는 것 ,, 따라서 화면에서 보여줄때는 if 절로 해결해야 한다

 

 

 

2. 질문 수정하기

eithers/views.py

def update(request, pk):
    question = Question.objects.get(pk=pk)
    if request.method == 'POST':
        form = QuestionForm(request.POST, instance=question)
        if form.is_valid():
            form.save()
            return redirect('eithers:detail', question.pk)
    else:
        form = QuestionForm(instance=question)
    context = {
        'form' : form,
        'question':question,
    }
    return render(request, 'eithers/update.html', context)

update.html

{% extends 'base.html' %}

{% block content %}
  <h1>UPDATE</h1>
  <a href="{% url 'eithers:index' %}">BACK</a>
  <hr>
  <form action="{% url 'eithers:update' question.pk %}" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value='UPDATE'>
  </form>
  <hr>
{% endblock content %}

 

 

3. 질문 삭제하기

eithers/views.py

def delete(request, pk):
    question = Question.objects.get(pk=pk)
    question.delete()
    return redirect('eithers:index')

 

 

4. 댓글 삭제하기

eithers/views.py

def comments_delete(request, question_pk, comment_pk):
    comment = Comment.objects.get(pk=comment_pk)
    comment.delete()
    return redirect('eithers:detail', question_pk)

 

 

5. Team 별로 댓글에서 선택한 개수, 득표율 표시하기

eithers.views.py

def detail(request, pk):
    question = Question.objects.get(pk=pk)
    comment_form = CommentForm()
    comments = question.comment_set.all()
    red = question.comment_set.filter(pick = False).count()
    blue = question.comment_set.filter(pick = True).count()
    cnt = question.comment_set.all().count()
    percent_r = (red / cnt) * 100
    percent_b = (blue / cnt) * 100
    context = {
        'question' : question,
        'comment_form' : comment_form,
        'comments' : comments,
        'percent_r' : percent_r,
        'percent_b' : percent_b,
        'red' : red,
        'blue' : blue,
    }
    return render(request, 'eithers/detail.html', context)

 

 

 

6. detail.html

{% extends 'base.html' %}

{% block content %}
  <h1>DETAIL</h1>
  <br>
  <h3>{{ question.title }}</h3>
  <hr>
  <a href="{% url 'eithers:update' question.pk %}">UPDATE</a>
  <form action="{% url 'eithers:delete' question.pk %}" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value='DELETE'>
  </form>
  <br>
  <p>Red TEAM</p>
  <p><b>{{ question.issue_a }} => {{ red }}명 선택 &#40;{{ percent_r }}&#37; &#41; </b></p>
  <br>
  <br>
  <p>Blue TEAM</p>
  <p><b>{{ question.issue_b }} => {{ blue }}명 선택 &#40;{{ percent_b }}&#37; &#41;</b></p>
  <hr>
  <a href="{% url 'eithers:index' %}">BACK</a>
  <hr>
  <b>댓글 작성</b>
  <form action="{% url 'eithers:comments_create' question.pk %}" method="POST">
    {% csrf_token %}
    {{ comment_form.as_p }}
    <input type="submit", value='작성'>
  </form>
  <hr>
  <b>댓글 목록</b>
  <br>
  <ul>
    {% for comment in comments %}
      {% if comment.pick == False %}
        <p>Red - {{ comment.content }}</p> 
      {% else %}
        <p>Blue - {{ comment.content }}</p> 
      {% endif %}
      <form action="{% url 'eithers:comments_delete' question.pk comment.pk %}" method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value='del'>
      </form>
    {% endfor %}
  </ul>
{% endblock content %}

 

  

 

 

 

오랜만에 우리반 깔깔즈와 나들이- 언제와도 좋은 걸

'Web > Django' 카테고리의 다른 글

URL  (0) 2022.10.17
pjt  (0) 2022.10.07
쿠키와 세션  (0) 2022.09.08
Django Form  (0) 2022.09.07
render vs redirect  (0) 2022.09.05

댓글