[DJANGO] CRUD: POST & GET 로직
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