21.2.26

커피 내리는 그냥 사람·2021년 2월 26일
1

위코드 pre코스

목록 보기
24/28

<Django CRUD 2>

CRUD1에서 만든 데이터베이스 및 모델에 HTTP 리퀘스트(GET, POST) 주기 실습 과제

1. 세팅

  1. 가상환경 세팅 및 장고, mysqlclient 설치

  2. settings.py설정

  • 추가되는 점 : corsheaders, 즉 보안 관련 설정

왜? : 클라이언트와 데이터를 직접 주고 받는 과정이다. 이에 따른 보안 설정이 없으면 안 되기 때문에. (보안에 관련한 자세한 내용은 노션 자료를 참고할 것. 블로그 최대한 이해 해보기)


  • 과정 :
  1. pip install django-cors-headers

  2. settings.py 설정

  • install부분에 'corsheaders' 추가.
  • middle~ 부분에
    'corsheaders.middleware.CorsMiddleware', 추가
  1. 값 정의
#REMOVE_APPEND_SLASH_WARNING
APPEND_SLASH = False

##CORS
CORS_ORIGIN_ALLOW_ALL=True
CORS_ALLOW_CREDENTIALS = True

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
)

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
		#만약 허용해야할 추가적인 헤더키가 있다면?(사용자정의 키) 여기에 추가하면 됩니다.
)
  1. 이후 작성했던 westarbucks의 내용을 불러온다.
    CRUD1

  1. client 역할을 할 httpie를 설치한다.
    brew install httpie
  • 설치 후 정상 작동을 확인하는 법 : http 후 엔터

2. urls.py 설정

urls.py는 크게 두 가지로 나눌 수 있다. 먼저 프로젝트 디렉토리에 있는 urls.py. 이를 큰형님 url이라고 생각하자. 그리고 두 번째 urls.py는 앱 안에 생성한다. 이를 작은형님 url이라고 부르자.

  1. 작동 원리 : 클라이언트의 요청이 들어오면(리퀘스트) 먼저 urls.py를 만나게 된다. urls.py가 정상 작동을 허가해야만 요청이 장고 안에서 돌 수 있다. 이 때 큰형님 url이 먼저 요청을 만나고, 그 요청이 작은형님 url로 간 다음, 모두 이상이 없는 경우 views.py로 이동한다. 이 플로우를 먼저 이해해야 urls.py의 코드를 작성할 수 있다.

westarbucks/urls.py

from django.urls import path, include

urlpatterns = [
    path('product', include('products.urls')),
]
  • 클라이언트의 요청을 가장 먼저 받는 곳이다. 그러므로 장고에서 기본으로 제공해주는 module을 사용하여 요청을 받으면 되는데 이때 사용하는 것이 path와 include다.
    path에는 사용자가 원하는 url 이름을 적어주고(프로젝트와 연관된 명확한 것이 좋다.) include는 앱명.urls를 해주면 된다. 이 때 큰형님 자리의 url 명은 비워두면 안 된다.

여기서 왜 product를 넣었을까? : 이건 추후에 만들다가 수정한 것이긴 하지만 기본적으로 큰형님에서 작은형님으로 이동하게되면 지어놓은 저 이름은 사라진다. 작은형님에서는 빈칸으로 이동한 것을 받게 되는데 이 때 첫 줄에서 코드가 끝나버리는 상황이 발생하여 큰 path밑에 아무리 값을 추가해도 내가 요청을 보내줄 수가 없게 된다. 따라서 큰형님 자리에 기준이 되는 path 명을 하나 정하고 작은형님 자리를 비워두지 않고 작은 가지를 친다는 느낌으로 path를 정해줘야 한다. 아래 작은형님 urls를 보면 이해할 수 있다.

products/urls.py

from django.urls import path
from .views import CategoryView, DrinkView


urlpatterns = [   
    path('/category', CategoryView.as_view()),
    path('/drink', DrinkView.as_view())

즉 httpie에서 검색 시 /product/category 이런 식으로 검색이 가능해진다는 것이다.

3. views.py 본격적으로 설정해보기

urls.py를 정상적으로 거친 요청을 views.py를 거쳐 데이터베이스 내용을 꺼내오거나 새로 추가하는 부분이다.

이 때 GET / POST가 중요한데

  • GET : 프론트 입장에서 백엔드에게 데이터를 줘! 라는 느낌
  • POST : 프론트 입장에서 백엔드에게 이 데이터를 넣어 줘! 라는 느낌

이다.

1. GET
  1. 환경 셋팅 : 환경에 맞게 장고 모듈을 임포트 후 models.py의 원하는 클래스를 가지고 온다.
    현재 진행된 내용은 category, drink, 그리고 Foreign key를 가져오기 위한 menu다.
from django.views import View # View 세팅
from django.http  import JsonResponse # http 통신 위한 세팅

# 왜 제이슨? : 자바스크립트를 해석하기 위해서.
# 말 그대로 자바스크립트로 온 애를 응답해주기 위해서 쓰는 것이다! 라고 생각

from .models import Category, Menu, Drink
  1. 클래스문 작성

과정
1) 요청을 받는다(따로 코드는 없음)
2) 데이터베이스에 알맞은 쿼리를 날려준다.
3) 결과를 가공한다.
4) json 형태로 body에 담아서 리턴한다.

class CategoryView(View): # 상속 , 이름은 명확하게.
    def get(self, request): # 클래스의 특징, request 받기
        categories = Category.objects.all() # 카테고리의 모든 객체를 가져오겠다.
        result     = [] # 왜 빈 리스트를 만들까? 
        -> 데이터베이스에서 온 쿼리셋은 파이썬이 아니다. 그냥 그렇게 생겼을 뿐. 
        그래서 한 번 풀어주고 리스트에 담으려고 하는 것.
        
        for category in categories: # 반복문
            my_dict = {				# 결과를 가공. 쿼리->파이썬
                'name' : category.name,
                'menu' : category.menu.name
            }
            result.append(my_dict)
            
        return JsonResponse({'result' : result}, status=200) # 파이썬 -> json
  • 여기서 다른 예제할 때 났던 오류 : 드링크 부분이었는데 여기서 가져온 객체가 str일 경우 끝에 .name을 쓸 수 없다고 나온다. 그래서 다음과 같이 했다.
AttributeError: 'str' object has no attribute 'name'```


```python
        for drink in drinks:
            my_dict = {
                'korean_name'  : drink.korean_name,
                'englshi_name' : drink.english_name,
                'description'  : drink.description,
                'category'     : drink.category.name
                
            }

왜? : str 객체는 'name(models.py에서 가져온)'을 인자로 받을 수 없었기 때문이다.

  • 참고 : 에러는 runserver(python manage.py runserver)에서 지속적으로 확인 가능하다.
  1. httpie 결과 확인
    http -v GET 127.0.0.1:8000/product/category를 통해 확인한다.
    200이 정상, 400대는 네트워크 문제, 500은 VSC를 다시 봐야한다.

2. POST
  1. 환경 설정
import json # 자바스크립트로 온 추가 요청을 받아야한다. 그러므로 json을 추가해준다.

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

from .models import Category, Menu, Drink # 혹시 새로 추가된 사항이 있다면 해준다.
  1. def 함수 만들기

과정
1) 요청을 받는다(body->json)
2) json -> 파이썬
3) 데이터베이스에 쿼리를 날린다.(create)
4) json 형태로 body에 담아서 리턴한다.

    def post(self, request): # 인자 마찬가지로 설정
        data     = json.loads(request.body) # json으로 데이터를 받아오니까.
        menu     = Menu.objects.get(name=data['menu']) # Foreign key
        category = Category.objects.create( # python shell 입력하는 양식과 거의 유사
            name = data["name"], # 형식 잘 봐두기
            menu = menu	# Foreign key
        )
        
        return JsonResponse({'MESSAGE':'SUCCESS'}, status=201) # 응답 반환
  1. httpie에서 실제로 POST가 되는지 확인한다.
http -v POST 127.0.0.1:8000/drink korean_name="아메리카노" english_name="Americano" description="깔끔하고 고소한 아메리카노" category="에스프레소"

결과 :

모든 결과는 SQL에서 실시간으로 확인할 수 있다. 이 플로우를 이해려고 하자.


2번째 할 때 났던 에러들

http: error: ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8000): Max retries exceeded with url: /product/category (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x10b08f6a0>: Failed to establish a new connection: [Errno 61] Connection refused')) while doing a GET request to URL: http://127.0.0.1:8000/product/category

runserver 안 하고 httpie 하면 나는 에러

ModuleNotFoundError: No module named 'productscorsheaders'

corsheaders Install 부분에 적을 때 콤마 안 찍어서 생기는 에러.

profile
커피 내리고 향 맡는거 좋아해요. 이것 저것 공부합니다.

2개의 댓글

comment-user-thumbnail
2021년 4월 28일

에러정보 알려주셔서 감사합니다 ㅎ

1개의 답글