[TIL] Django CRUD3

Jene Hojin Choi·2021년 1월 31일
2

Django

목록 보기
3/12
post-thumbnail

Introduction to CRUD3

저번 글인 CRUD2에서는 models.py 작성을 보았다.
이번에는 views.py에서 POST, GET을 보겠다. 역시나 아래와 같은 모델을 사용한다.


이제 스타벅스에서 마이너한 음료 이름까지 외워버렸다.
제주에만 가서 먹을 수 있는 '제주 쑥떡 크림 프라푸치노', '제주 쑥쑥 라떼'
제주도 가면 꼭 먹고싶다.

참고로 내가 짠 views.py가 효율적인지, 실제로 현업에서 이런 식으로 쓰는지는 정확하지 않다!! 참고만 해주시길 바란다. 한달후에 더 많은 지식이 쌓이고 돌이켜보면 굉장히 부족할 수도 있다고 생각한다.
만약 틀린 부분이 있다면 댓글 꼭 달아주길 바란다.

Tree로 현재 project, app 확인

westarbucks 폴더에 products 라는 app이 있음.
아래는 westarbucks 폴더에서 terminal 에 tree를 입력한 상황:

1. View (views.py)

view는 http request에 맞는 response를 해주어야하는 파이썬 function을 담고 있다.
CRUD1 글에서 썼듯, 드디어 진짜로 CRUD를 할 차례이다!

Create - POST
Read - GET
Update - PATCH
Delete - DELETE

import

  1. import json: json은 파이썬의 built-in module이다. json 데이터를 읽고 해석하는 역할을 한다. 이게 없다면 http request의 데이터를 읽어내지 못한다!

  2. from django.http import JsonResponse : JsonResponse 는 HttpResponse라는 class의 subclass(하위 클래스)이다. django.http 는 module이다. json 데이터를 리턴하기 쉽게 만들어주는 클래스이다.

  3. from django.views import View: View란 역시 class이고, django.views는 module이다. views.py 안에 있는 모든 클래스들이 View를 inherit 해야하므로 (상속 받아야하므로) 반드시 import 해주어야한다.

  4. from products.models import Menu, Category, Drink, Allergy, Allergy_drink, Image, Nutrition: products안의 models.py에서 뒤에 있는 클래스를 import하라는 뜻이다.

2. CREATE: post

http -v POST

나는 위와 같이 http -v post 요청을 보내는 것으로 생각을 했다.
post 함수를 실행시키기 전에 데이터를 어떤 형식으로 request를 요청할지 생각해볼 수 있다.

  1. allergy는 여러개가 있을 수 있기 때문에 list 형식
  2. nutrition은 dictionary 형식
  3. 참고로 위의 "", '', : 하나하나 다 신경 써야한다. 문법이다! "" 대신에 '' 쓰면 에러난다. 개복치이기 때문이다

이 사이트 http request 보내시는 분은 꼭 읽으시길!
https://devhints.io/httpie 에서 http request 보낼 때 쓰이는 문법을 엿볼 수 있다

class ProductsView(view)

post는 class ProductsView(View)아래에 def post(self, request) 라는 함수를 만들어 구현할 것이다.
data = json.loads(request.body): data라는 변수에 request.body에 있는 것을 받는다는 것이다.

받은 데이터는 아래와 같이 여러 변수에 담아둔다.

.objects.get_or_create(): 이미 존재하면 안 만들고, 없으면 만들어주는 함수

이건 정말 꿀팁인데, 그냥 objects.create 가 아니고 get_or_create를 하면 없으면 만들고 있으면 연결시켜줄 수 있다.

근데 한가지 주의할 점이 있다.
위의 소스코드를 보면 menu = menu[0], category = category[0]이라고 써있다. 왜 이렇게 썼을까??

✅ get_or_create returns tuple!!!

데이터베이스에 이름이 '럼 샷 코르타도'이고 category_id 가 5 (에스프레소)인 drink가 이미 존재하는 상황이다. 이런 상황에서, 아래와 같이 파이썬 쉘을 켜고 drink1이라는 변수에 이 Drink의 instance를 담아보면?

✅ (object, True or False)

drink1이 (<Drink: Drink object (7)>, False)로 나오는 것을 확인할 수 있다.

False: 이미 존재한다
True: 존재하지 않는다. 만들어준다.

my version of post()

3. READ: get

get 함수도 class ProductsView(View) 안에 만들어주었다.
post 요청을 보냈을 때처럼 리턴받고 싶었던 데이터의 형식을 생각해보았다.

  1. 전체는 dictionary 형태일것
  2. "allergy" : list 형태
  3. "nutrition" : dictionary 형태

drink 하나당 result 하나씩

  • 일단 drinks 라는 함수에 데이터베이스에 있는 모든 Drink instance, 즉 object 를 담았다.
    그리고 반환할 결과인 list 형태의 result를 만들었다.

  • 각각의 drink에 대해서 result 가 하나씩 있어야하므로 for drink in drinks:로 for loop을 돌렸다.

allergy 여러개가 list로

allergies라는 변수에 그 drink가 가진 알러지를 담은 모든 객체를 담았다. 고로 allergies 는 queryset인 상태이다.

  • result 안에 allergy는 list 로 내보내주기 위해 list comprehension을 사용하여 값을 넣어주었다. 알러지 이름만 담고 싶으므로 각 allergy 당 allergy.name 만 담을 수 있도록 하였다.

nutrition 은 dictionary 형태로

위의 소스코드에서 일부분만 보자.

nutrition 을 dictionary 형태로 내보내기 위해 나는 일단

  1. 해당하는 drink의 nutrition object 을 filter를 통해 받았다. -> queryset 이다.
  2. 그 queryset의 .values()를 쓰면 또 queryset이 나온다.
  3. 그 queryset의 0번째 인덱스는 우리가 원하는 딕셔너리 형태이다.

아래는 파이썬 shell에서의 실험 결과이다.

my version of get()

test

Wrap-up

  1. post에서:
    있으면 안 만들고, 없으면 만들고 싶다면 get_or_create()를 쓰자
    get_or_create()는 tuple을 리턴한다.

  2. get에서:
    리턴 받을 데이터의 형태를 생각하자. allergy는 list로, nutrition은 dictionary로 받자.
    filter()는 queryset을 리턴한다.

최대한 알기 쉽게 쓰려고 했는데도 나의 글쓰기 솜씨는 한없이 부족한 것 같다.
다음 기수의 위코드분들이 이걸 보고 꼭 도움 받았으면 좋겠다.

위코드 멘토님들은 1을 알려주면 10을 해보기를 바라신다. 그래서 나도 열심히 굴렀다. 구르고 구르면서 동기들과 상의해가면서 이런 함수를 써야하는구나, 이런 식으로 코드를 짜야하는구나 알았다.

물론 내 코드가 정답일 것 같지는 않지만, 정답에 60프로라도 가깝다면 진짜 누군가에게 도움이 되기를 바란다.
누군가에게 도움이 되고 싶던 호진이가... 이만 총총....

2개의 댓글

comment-user-thumbnail
2021년 2월 1일

엄청난 도움이 될것입니다 >< 잘 읽었습니다~~~ ❤️

답글 달기
comment-user-thumbnail
2021년 2월 2일

엄청난 도움이 되었습니다 >< 꺅 감사합니다~~(하뚜)

답글 달기