Model Join Restaurant 모델에는 음식점 이름, 카테고리(한식, 중식 등), 주소 정보가 있으며, Review 모델에는 제목, 리뷰, 사진 정보가 있다.
이를 모두 한 template에 하나의 view로 보여주고 싶었다. Review 모델이 forienkey field로 Restaurant을 참조하고 있으니 Join을 생각했고, 각 모델의 데이터를 한 번에 보여줄 방법을 찾아봤다.
모델 코드 참고
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import PIL # Review 모델의 imagefield를 위해 추가 from django.db import models class Restaurant(models.Model) : cat_food = ( ("한식","한식"), ("중식","중식"), ("일식","일식"), ("양식","양식"), ) name = models.CharField(max_length=30) location = models.CharField(max_length=100) category = models.CharField(max_length=10, choices=cat_food) ...(생략)... class Review(models.Model) : restaurant = models.ForeignKey(Restaurant, on_delete=models.PROTECT) #참조키 title = models.CharField(max_length=50) review = models.TextField() photo = models.ImageField(upload_to="reviewBoard/images", blank=True) # 처음 이미지를 업로드하면 media 폴더가 자동으로 생성된다. ...(생략)...
Django ORM CookBook 8퍼센트 프로덕트팀에서 번역한 ORM CookBook을 참고했다.
참고: ORM CookBook
1 2 3 4 5 >>> restaurants = Review.objects.select_related('restaurant') #foreignkey 변수 이름 >>> restaurants <QuerySet [<Review: 은성밥차 맛집 리뷰>]>
select_related() 함수에 Review 모델이 foreignkey로 잡은 restaurant이라는 이름을 인자로 전달했다. 겉보기에는 일반적인 Review 데이터를 가져온 것 같지만 SQL 문으로 보면 INNER JOIN의 결과라는 걸 알 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >>> print(restaurants.query) SELECT "reviewBoard_review"."id", "reviewBoard_review"."restaurant_id", "reviewBoard_review"."title", "reviewBoard_review"."review", "reviewBoard_review"."photo", "reviewBoard_restaurant"."id", "reviewBoard_restaurant"."name", "reviewBoard_restaurant"."location", "reviewBoard_restaurant"."category" FROM "reviewBoard_review" INNER JOIN "reviewBoard_restaurant" ON ("reviewBoard_review"."restaurant_id" = "reviewBoard_restaurant"."id")
참조하는 테이블_set.all() 하지만 위 쿼리셋에서 어떤 방법을 써야 Restaurant 모델의 데이터를 가져올 수 있는지 알 수 없었다. 그래서 다른 방법을 스택 오버 플로우에서 찾았다.
참고: ORM CookBook
인터랙티브 셸에서 확인
1 2 3 4 5 >>> from reviewBoard.models import Restaurant, Review >>> r2 = Restaurant.objects.all() >>> r2[0].review_set.all() <QuerySet [<Review: 은성밥차 맛집 리뷰>]>
참조당하는 테이블 Restaurant의 데이터 객체에서 참조하는 테이블(소문자)_set.all()과 같은 형태로 적어주면 관계 테이블의 데이터를 가져올 수 있다.
views.py
1 2 3 4 def index(request) : restaurants = Restaurant.objects.all() return render(request, "reviewBoard/index.html", {'restaurants' : restaurants})