Django/inflearn

리뷰 등록 구현하기

곽수진 2022. 12. 3. 22:01
반응형

from django.urls import path
from . import views

urlpatterns = [
    path('list/', views.list, name="list"),
    path('create/', views.create, name="restaurant-create"),
    path('update/', views.update, name="restaurant-update"),
    # path('detail/', views.detail, name="restaurant-detail"),
    path('delete/', views.delete, name="restaurant-delete"),

    path('restaurant/<int:id>/', views.detail, name="restaurant-detail"),
    path('restaurant/<int:restaurant_id>/review/create', views.review_create, name="review-create")
]

▶ 기존에 구현된 detail 화면의 url 패턴을 path parameter를 이용해 수정함

▶ 리뷰를 작성하는 review-create 화면의 url 패턴을 path parameter를 이용해 작성함

 

 

from django.shortcuts import render, get_object_or_404, redirect
from third.models import Restaurant, Reviews
from django.core.paginator import Paginator
from third.forms import RestaurantForm, ReviewForm
from django.http import HttpResponseRedirect

# Create your views here.
def list(request):
    restaurants = Restaurant.objects.all()
    paginator = Paginator(restaurants, 5)

    page = request.GET.get('page')
    items = paginator.get_page(page)

    context = {
        'restaurants': items
    }
    return render(request, 'third/list.html', context)


def create(request):
    if request.method == 'POST':
        form = RestaurantForm(request.POST)
        if form.is_valid():
            new_item = form.save()
        return HttpResponseRedirect('/third/list/')
    form = RestaurantForm()
    return render(request, 'third/create.html', {'form': form})


def update(request):
    if request.method == 'POST' and 'id' in request.POST:
        # item = Restaurant.objects.get(pk=request.POST.get('id'))
        item = get_object_or_404(Restaurant, pk=request.POST.get('id'))
        form = RestaurantForm(request.POST, instance=item)
        if form.is_valid():
            item = form.save()
    elif request.method == 'GET':
        # item = Restaurant.objects.get(pk=request.GET.get('id'))
        item = get_object_or_404(Restaurant, pk=request.GET.get('id'))
        form = RestaurantForm(instance=item)
        return render(request, 'third/update.html', {'form': form})
    return HttpResponseRedirect('/third/list/')


def detail(request, id):
    if 'id' is not None:
        item = get_object_or_404(Restaurant, pk=id)
        reviews = Reviews.objects.filter(restaurant=item).all()
        return render(request, 'third/detail.html', {'item': item, 'reviews': reviews})
    return HttpResponseRedirect('/third/list/')


def delete(request):
    if 'id' in request.GET:
        item = get_object_or_404(Restaurant, pk=request.GET.get('id'))
        item.delete()
    return HttpResponseRedirect('/third/list/')


def review_create(request, restaurant_id):
    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid():
            new_item = form.save()
        return redirect('restaurant-detail', id=restaurant_id)

    item = get_object_or_404(Restaurant, pk=restaurant_id)
    form = ReviewForm(initial={'restaurant': item})
    return render(request, 'third/review_create.html', {'form': form, 'item': item})

▶ url에서 정수형의 id parameter를 전달받기 때문에 views.py의 create 메소드에서 직접 이 변수명을 받을 수 있음

def detail(request, id) : restaurant의 id(pk)를 직접 url path parameter을 통해 전달 받음

reviews = Review.objects.filter(restaurant=item).all() : reviews 변수에 리뷰 리스트를 모두 담아 띄움

 

▶ def review_create(request, restaurant_id) : restaurant_id를 직접 url path parameter을 통해 전달 받음

if form.is_valid() : 데이터가 form 클래스에서 정의한 조건을 만족하는지 체크함

new_item = form.save() : save 메소드로 입력받은 데이터를 레코드로 추가

return redirect('restaurant-detail', id=restaurant_id) : 전 화면으로 이동함

 

 

{% extends 'third/base.html' %}
{% load static %}
{% block content %}
<div class="container">
    {% for item in restaurants %}
    <div class="row restaurant-item" style="margin:20px auto;">
        <div class="col-sm-12">
            <div class="card border-secondary">
                <div class="card-body">
                    <h5 class="card-title">{{ item.name }}</h5>
                    <h6 class="card-subtitle mb-2 text-muted">{{ item.address }}</h6>
                    <p class="card-text">음식점 설명</p>
                    <a href="{% url 'restaurant-detail' id=item.id %}" class="card-link">자세히 보기</a>
                    <a href="{% url 'restaurant-update' %}?id={{ item.id }}" class="card-link">수정하기</a>
                </div>
            </div>
        </div>
    </div>
    {% endfor %}

    <div class="row">
        <div class="col-sm-12 text-center">
            <div class="pagination">
                <span class="step-links text-center" style="width:100%;">
                    {% if restaurants.has_previous %}
                        <a href="?page=1">&laquo;</a>
                        <a href="?page={{ restaurants.previous_page_number }}">{{ restaurants.previous_page_number }}</a>
                    {% endif %}
                    <span class="current">
                        {{ restaurants.number }}
                    </span>
                    {% if restaurants.has_next and restaurants.next_page_number != restaurants.paginator.num_pages %}
                        <a href="?page={{ restaurants.next_page_number }}">{{ restaurants.next_page_number }}</a>
                        <a href="?page={{ restaurants.paginator.num_pages }}">{{ restaurants.paginator.num_pages }}</a>
                    {% elif restaurants.has_next and restaurants.next_page_number == restaurants.paginator.num_pages %}
                        <a href="?page={{ restaurants.next_page_number }}">{{ restaurants.next_page_number }}</a>
                    {% endif %}
                </span>
            </div>
        </div>
    </div>
</div>
{% endblock %}

▶ 기존 list 화면의 '자세히보기' 링크 수정

 

 

list 화면

 

 

from django.forms import ModelForm
from django import forms
from third.models import Restaurant, Reviews
from django.utils.translation import gettext_lazy as _

REVIEW_POINT_CHOICES = (
    ('1', 1),
    ('2', 2),
    ('3', 3),
    ('4', 4),
    ('5', 5)
)

class ReviewForm(ModelForm):
    class Meta:
        model = Reviews
        fields = ['point', 'comment', 'restaurant']
        labels = {
            'point': _('평점'),
            'comment': _('코멘트')
        }
        help_texts = {
            'point': _('평점을 입력해주세요.'),
            'comment': _('코멘트를 입력해주세요.')
        }
        widgets = {
            'restaurant': forms.HiddenInput(),
            'point': forms.Select(choices=REVIEW_POINT_CHOICES)

        }

class RestaurantForm(ModelForm):
    class Meta:
        model = Restaurant
        fields = ['name', 'address']
        labels = {
            'name': _('이름'),
            'address': _('주소'),
        }
        help_texts = {
            'name': _('이름을 입력해주세요.'),
            'address': _('주소를 입력해주세요.')
        }
        error_messages = {
            'name': {
                'max_length': _('이름이 너무 깁니다. 30자 이하로 작성해주세요.')
            }
        }

REVIEW_POINT_CHOICES : 리뷰 생성 로직을 구현하기 위해 forms.py에 평점의 선택지를 정의

'restaurant' : forms.HiddenInput() : 리뷰를 작성할 식당 정보는 사용자에게 보여지지 않도록 함

'point' : forms.Select(choices = REVIEW_POINT_CHOICES) : 선택지를 인자로 전달

 

 

{% extends 'third/base.html' %}
{% load static %}
{% block content %}
<div class="container">
    <form action="{% url 'review-create' restaurant_id=item.id %}" method="post">
        {% csrf_token %}
        <table>
            {{ form.as_table }}
        </table>
        <button type="submit">등록</button>
    </form>
</div>
{% endblock %}

▶ 리뷰를 작성하는 페이지 생성

 

 

{% extends 'third/base.html' %}
{% load static %}
{% block content %}
<div class="container">
  <div class="row">
    <div class="col-sm-12" style="margin-top:20px;">
      <h3>{{ item.name }}</h3>
      <p>
        {{ item.address }}
      </p>
      <p>
        <a href="{% url 'restaurant-delete' %}?id={{ item.id }}">
          <button class="btn btn-danger">삭제하기</button>
        </a>
      </p>
      <hr/>
      <p>
        <a href="{% url 'review-create' restaurant_id=item.id %}">
          <button class="btn btn-info">리뷰쓰기</button>
        </a>
      </p>
      {% for review in reviews %}
        {{ review.comment }} - {{ review.point }}점
      {% endfor %}
    </div>
  </div>
</div>
{% endblock %}

▶ 기존의 detail 화면에서 리뷰 쓰기 링크 추가

{% for review in reviews %} {{ review.comment }} - {{ review.point }}점 {% endfor %} : reviews에 담긴 모든 내용을 review에 담아 for문으로 돌리며 comment와 point를 출력

 

 

자세히 보기 화면

 

 

리뷰 작성 화면
리뷰 작성을 완료한 후 detail로 돌아온 화면

반응형

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

Join 개요  (0) 2022.12.05
리뷰 삭제 구현하기  (0) 2022.12.04
Relation 모델 선언하기  (0) 2022.12.01
Relation 개요  (2) 2022.11.30
D : 게시글 삭제 구현하기  (0) 2022.11.12