DEV/🟢 DJANGO

[DJANGO] CRUD: POST & GET 로직

개발을 하게 되. 2021. 8. 22. 20:50

 HTTPIE 를 통한 Requset  

 

로컬에서 shell 을 통해 데이터를 넣을 수 있는 방법도 있지만 

httpie라는 http 통신을 통해 client 인척 하고 직접 서버에 요청을 하고 장고가 작성한 어플리케이션 코드를 실행해서 데이터 베이스를 생성하고 불러올 수 있다. 이때 post(생성) 과 get(조회) 메소드에 대해 알아보자. 

 

이때 중요한 건 요청 request 는 post (데이터 삽입) 개념과 get (데이터 조회)이 있다는 것을 생각하자. 

web client의 HTTP 요청 ( https://127.0.0.1/products) 을 하면 URL conf (url.py) 가 분석하여 요청을 처리하기 위한 로직( View.py)를 실행시키고 마지막으로 데이터베이스와 통신 (model.py) 해서 데이터 작업을 수행하고 요청에 맞는 HTTP응답을 client에게 보내줄 수 있는 Backend API를 구현한다. 

Web client(요청) → URL config (url.py) 에서 url 분석 → View.py(로직 실행) → 데이터 베이스와 통신 (model.py)
→ HTTP 응답 

POST Method 

1. Client 준비 

1️⃣  우선 HTTP request를 할 수 있는httpie를 설치하자 

brew install httpie

2️⃣  Body에 담을 data 만들기

Body 에 담아서 보낼 data를 만들자. 

{
		"menu" : "음료",
		"category" : "콜드브루",
		"product" : "맛있는 콜드브루"
}

3️⃣ HTTP 요청 보내기 

앱 product로 연결해서 데이터값을 넣어라

프론트 없이 내부적으로 보낸 것이다. 내가 만든 백엔드 프로세스가 잘하나 확인하는 작업이다. 

http -v POST 127.0.0.1:8000/products menu='음료' category='콜드브루' product='맛있는 콜드브루'

 

 

2. View 파일 작성하기 

이제 요청을 보냈다. 당연히 아무것도 만들지 않았으니 에러가 뜰 것이다. 

이러한 요청에 반응하도록 하는 view.py 파일을 수정하자. 위치는 당연히 앱 내에 있는 view.py

여기서는 json란 걸 사용하는데 자바스크립트를 파이썬으로 바꿔주는 역할로 우선은 생각하자. 

간략하게 말해 데이터를 저장하거나 전송할때 많이 사용되는 경량의 Data 교환형식이다. 

view.py 작성 

#products/views.py

import json

from django.http     import JsonResponse
from django.views    import View

from products.models import Menu, Category, Product
#데이터틀 가져옴. 
#products앱 모델에서 메뉴,카테고리,상품 모델을 가져옴

class ProductsView(View):
    def post(self, request): #http request보따리를 말하는 것임 
		data     = json.loads(request.body)
        # request.body 제이슨 형태로 데이터가 반환되기때문에 json을 파이썬언어로 바꿔야함
        # 밑에 처럼 딕셔너리 형태로 반환됨. 
        # {menu:'음료', category:'콜드브루', product: '맛있는 콜드브루'} 

		menu     = Menu.objects.create(name= data['menu']) #'음료' 값이 들어감
		#menu = Menu.object(name='음료') 객체로 저장 
		category = Category.objects.create(
                name = data['category'], #'콜드브루'값이 들어감 
                menu = menu #FK 
        )
      	#category = Category.object(name='음료', menu= menu) 객체로 저장

        
        Product.objects.create(
                name     = data['product'], #'맛있는 콜드브루'
                category = category, #FK로 처리하기 때문에 data index필요없음
                menu     = menu #FK로 처리하기 때문에 data index 필요없음 
        )

        return JsonResponse({'MESSAGE':'CREATED'}, status=201)
        #만약에 잘 전송되었다면(서버로 잘들어감)
        #(server to Client)로 보내고 상태는 201로 반환 
		#return 값은 프론트엔드가 보는 값임 간략하게 쓰는 것이 좋음

 

3. 서브 URL 생성, 작성 

view를 작성한 후에는 클라이언트의 요청을 받아 적절한 view를 맵핑해주는 urls.py 을 작성해야함.

쉽게 말해, 베이스 ulr.py 에서 어디 앱으로 갈건지를 분류했다면, 서브 url.py 에서 소분류를 하는 것이다 

.
├── manage.py
├── products
│   ├── models.py
│   ├── urls.py
│   └── views.py
└── westarbucks
    └── urls.py : main urls.py (요청 url 분석을 가장 먼저 하는 위치)
더보기

베이스 url.py 👉 127.0.0.1:8000/users 

서브 url.py 👉 127.0.0.1:8000/users/signin

앱 - 서브 URL에서 as_view 작성 

마지막에는 product - view 안에는 2개의 메소드 ( Post와 Get) 를 만들었다.

두개나 있는데 어디에 연결할지 모르기때문에 as_view추가해서 post와 get 을 구분해서 사용하도록 하자.

from django.urls import path

from products.views import ProductsView

urlpatterns = [
	path('', ProductsView.as_view()), #as_view???? 어떤 메소드임??? 
]
# 찾아보니 post 와 get 메소드의 중간자 역할을 하는 것 
# 클래스형 뷰는 클래스로 진입하기 위한 진입 메소드를 제공 
# 진입 메소드 = as_view() 에서 클래스 객체 생성
# dispatch() 메소드는 요청을 검사해서 HTTP메소드 (POST or GET) 인지 알아내고 
# 해당 메소드가 정의되어있지않으면 HttpReosponseNotAllwd 예외를 발생시킴

프로젝트 - 베이스URL작성 

이제 서브url 이 있다는 것을 베이스 url에 알리자. 그래야 처음 클라이언트 요청을 받을 수 있다. 

# westarbucks/urls.py

from django.urls import path, include

urlpatterns = [
	path('products', include('products.urls')),
]

 

4. Httpie로 Django.server에 요청보내기 

$ http -v POST 127.0.0.1:8000/product menu='음료' category='콜드브루' 
product='맛있는 콜드브루'

# /product => 앱 이름

성공하면 201 과 CREAT 메세지가 뜰 것이다. 

데이터가 잘 만들어졌다면 데이터가 실제 있는 MySQL에서 볼 수 있다. 

 

이제 요청으로 데이터 베이스로 들어간 상태

이제 get으로 클라이언트로 데이터를 조회할 수 있다. 

이때 데이터 주머니인 바디에 또 넣을 필요가 없고 그냥 뿌리면 된다. 

 


GET Method                                                    

1. View.py 작성하기

product - view.py 에 들어가서 get 메소드를 추가해서 Response를 할 수 있게 하자. 

#products/views.py
class ProductsView(View): 
	def get(self, request):
		products = Product.objects.all() 
        #all() 메소드는 쿼리셋으로 데이터반환 Product객체 모두 가져옴 
        #<Queryset [메뉴], [카테고리] ,[상품명] 쿼리셋으로 가져옴 
		
        results  = []
        for product in products: 
        #쿼리셋안에 있는 메뉴,카테고리,상품명 가져옴. product 는 퀘리셋이 아닌 객체 
        	results.append(
            	{
                	"menu"         : product.category.menu.name, #product객체 안 카테고리에 연결된 메뉴의 이름  
                	"category"     : product.category.name, #product객체 안 카테고리 이름 
                	"product_name" : product.name #product 객체 이름 
				}
			)
        	
        return JsonResponse({'resutls':results}, status=200)
        # results 반환함
		# "menu          : product.category.menu.name, 
		# "category"     : product.category.name,  
		# "product_name" : product.name

result안에 딕셔너리 형태로 넣고 뿌려준다고 생각하자. 

[ { 요청된 데이터 1 }, { 요청된 데이터2 }, { 요청된 데이터3} ]

 

처음 클라이언트로 부터 요청 받기 위한 main urls.py (westarbucks/urls.py) 와 연결해줘야한다.

(위에 설명과 같이 이미 연결되어 있고 메소드만 다르다면 동일한 url을 사용 하면된다.)

어차피 as_view에서 결정해주니깐 상관없는 것이다. 

# westarbucks/urls.py

from django.urls import path, include

urlpatterns = [
	path('products', include('products.urls')),
]
#서브url.py 
from django.urls    import path
from products.views import ProductsView

urlpatterns = [
    path('', ProductsView.as_view())
]

 

2.  Httpie로 Django.server에 요청보내기 

$ http -v GET 127.0.0.1:8000/products