결과물

룰렛 돌려서 한식, 중식, 일식, 양식 고르기

  • ORM은 아니다. javascript로 구현한 룰렛을 돌려서 추천한다.
  • codepen에 올려져 있는 javascript 코드를 조금 수정했다.



ORM으로 DB에 등록된 맛집을 랜덤으로 추천하기






views.py

random으로 맛집을 추천하는 randFood 앱의 views.py이다. django.db.models에서 Max, Avg 등 집계 함수를 import하고, reivewBoard앱에 있던 model들도 가져온다.


from django.shortcuts import render
from django.db.models import Max, Avg
from reviewBoard.models import Review, Restaurant
import random

def get_random_restaurant():
    max_id = Restaurant.objects.all().aggregate(max_id = Max("id"))['max_id']
    while True : 
        pk = random.randint(1, max_id)
        restaurant = Restaurant.objects.filter(pk=pk).first()
        if restaurant : 
            return restaurant

def index(request):
    restaurant = get_random_restaurant()
    score_avg = Review.objects.filter(restaurant__name=restaurant.name).aggregate(Avg('score'))

    return render(request, 'randFood/index.html', {'restaurant':restaurant, 'score_avg':score_avg})



무작위 데이터 추출

  • #1 : id중에서 제일 큰 수를 max_id 키에 매핑한 후 ['max_id']로 해당 id를 가져온다.
  • #2 : randint로 1에서 max_id까지의 수(randint는 max_id까지 포함한다.) 중 하나의 수를 무작위 추출해 pk 변수에 담는다.
  • #3 : filter 함수에 pk값을 인자로 전달해서 객체를 구한 후 restaurant 변수에 담는다.
  • #4 : 만약 restaurant 객체가 있다면 해당 객체를 반환하고, 존재하지 않는다면 다시 while문을 반복한다.


def get_random_restaurant():
    max_id = Restaurant.objects.all().aggregate(max_id = Max("id"))['max_id'] #1
    while True : 
        pk = random.randint(1, max_id) #2
        restaurant = Restaurant.objects.filter(pk=pk).first() #3
        if restaurant : #4
            return restaurant



  • #1 : 위에서 만든 get_random_restaurant() 함수로 무작위 restaurant 객체를 가져온다.
  • #2 : restaurant.name으로 Review 데이터를 filtering 해서 가져온다. 해당 식당의 리뷰 데이터만 가져온 후, Avg() 집계 함수로 score 필드의 값들을 평균 낸 후, score_avg 변수에 저장한다.
  • #3 : 딕셔너리 형태로 앞서 구한 데이터들을 전달한다.


def index(request):
    restaurant = get_random_restaurant() #1
    score_avg = Review.objects.filter(restaurant__name=restaurant.name).aggregate(Avg('score')) #2

    return render(request, 'randFood/index.html', {'restaurant':restaurant, 'score_avg':score_avg}) #3





urls.py

randFood의 urls.py에 views.py의 index() 함수를 url 주소와 매핑한다.


from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index' )
]





index.html

혼란스럽지 않게 하기 위해 ORM이 들어간 html 코드만 남겨두고, 나머지는 아래 코드에서 뺐다.



{% extends 'reviewBoard/base.html' %}
{% load static %}

{% block content %}

<div class="container pt-5">
        <h3 class="pt-5 text-center">땡기는 게 없다구요? 이 식당은 어때요? :)</h3>

        <!-- #1 -->
        <div class="py-3 text-center alert alert-info" role="alert">
            <h4>오늘의 맛집 : <strong> {{restaurant.name}} ( {{restaurant.category}} )</strong></h4>
            <h4>평균 평점 : <strong>{{score_avg.score__avg}}</strong></h4>
            <h4>주소 : <strong>{{restaurant.location}}</strong></h4>
        </div>
        
        <!-- #2 -->
        {% if restaurant.review_set.all %}
        <h4 class="py-3 text-center">리뷰 목록</h4>

        <hr class="mb-5" style="width:200px;"> 

        <!-- #3 -->
        {% for rev in restaurant.review_set.all %}
        <div class="mt-3 container d-flex justify-content-start" >

            <!-- #4 -->
            {% if rev.photo %}
                    <a href={% url 'reviewBoard:review-detail' rev.id %}></a>
                        <img src="{{ rev.photo.url }}" alt="reviewPhoto" class="img-thumbnail rounded review-thumb">
                    </a>
                    <br>
                    {% endif %}
                        <div class="ml-3">
                          <a href={% url 'reviewBoard:review-detail' rev.id %} 
                             style="color:gray; text-decoration: none;">
                              <h2>{{ rev.title }} </h2>
                            </a>
                            
                            <p>{{rev.updated_date | date}}</p>
                            <p> 평점 : {{ rev.score }}</p>

                            <p> {{rev.review | truncatechars:100 }}</p>
                            <a href="{% url 'reviewBoard:review-detail' rev.id %} "> 자세히 보기 </a>
            </div>
        </div>

        {% endfor %}
        {% endif %}

        <br>
        <br>

</div>
{% endblock %}



  • #1 : views.py에서 index() 함수가 템플릿에 {'restaurant':restaurant, 'score_avg':score_avg}로 데이터를 전달했다. 내 코드의 model 클래스를 보면 이해가 더 잘가겠지만, restaurant 데이터에 name이나 location, category 필드가 있어서 위와 같이 썼다.
  • #2 : 템플릿 태그에서 if restaurant.review_set.all 코드로 restaurant와 관련된 review 데이터가 존재하는지 확인한다.
  • #3 : 만약 있다면, restaurant와 관련된 review 데이터를 모두 가져오고 for문으로 반복변수 rev에 review 데이터를 하나씩 담는다.
  • #4 : 이 코드 부분은 reviewBoard의 index.html 부분을 그대로 가져왔다. 필드의 내용을 가져오는 것뿐이다.