TIL - Django - CRUD(2)

김영훈·2021년 4월 1일
0

Django

목록 보기
3/11

# Client를 사용해서 Server에 요청 보내기

  • Client 준비

    • Server에 HTTP request를 전송할 수 있는 http client 유틸리티 Httpie 설치 필요
    • brew install httpie
  • urls.py

    • client 요청이 목적에 맞게 app과 연결되어 처리될 수 있도록 구분(분류)하는 역할

    • 프로젝트 폴더 내부에 있는 urls.py

      • 은행에서 번호표를 뽑아주는 청원경찰의 역할과 같음. 로직에 돌입하기 전, 요청이 요구하는 app이 무엇인지를 파악해서 분류해줌 ex) http://localhost:8000/user —> user관련 업무를 처리하겠다는 요청이 호출됨

      • urls.py에 8000/ 뒤에 추가되는 ‘user’(창구)와 같은 패턴을 모두 등록해줘야 한다.

      • 요청과 연결될 app 이름string 형태로 지정(app 이름은 복수 형태ex.'users')로 지정하는 것이 좋다

      • include()로 요청이 app 내부의 urls.py와 연결되도록 지정

      • path("'서버주소/' 다음으로 입력될 부분", include('app 이름.urls'))
        ex)

        urlpatterns = [
        	path('user', include('users.urls'))
        ]
        
        
        
    • app 폴더 내부에 있는 views.py:

      • View 불러오기: ex) from django.views import View

      • models.py의 class(테이블) 불러오기: ex) from .models import User(product app에서 불러오므로, .(dot)만 입력하면 됨)

      • class view생성(View 상속) 뒤, 구현하고자 하는 로직을 함수 형태로 입력

        # 예시
        from django.shortcuts import render
        import json
        from django.http import JsonResponse
        
        from django.views import View
        from .models import Menu, Category
        
        class MenuView(View):   # class view 생성하려면 View를 상속받아야 한다!!
            def get(self, request):
                return JsonResponse({'message': 'Success!'}, status=200)
    • app 폴더 내부에 있는 urls.py:

      • 스크립트 파일 새롭게 생성해야 함

        • path 불러오기
        • path(‘’) : ‘8000/user’ 뒤에 특별히 추가할 게 없다면 비워놓으면 된다.
        • views.py에서 생성한 class view 불러오기
        • settings.py의 urls.py에서처럼 include()를 사용하여 특정 파일(ex. urls.py)과 연결하는 대신, 불러온 class view연결해준다.
        • as_view(): django에서 생성한 함수로, client의 요청이 GET인지 POST인 구별하여 적절한 메소드를 실행시켜준다.
        # 특별히 추가할 서버 주소가 없는 경우
        urlpatterns = [
        	path('', UserView.as_view())
        ]
        
        # 추가할 서버 주소가 있는 경우
        urlpatterns = [
           path('/owner', OwnerView.as_view()),
           path('/dog', DogView.as_view()),
        ]
        
    • 응답(response) 메시지 설정하기

      • 실제 프로젝트 진행할 땐 modelslpy --> views.py --> urls.py 순서로 작성하는 것이 좋다.

      • views.py의 get메소드에서 return결괏값으로 응답 메시지를 지정할 수 있다.

      • JsonResponse() 불러와서 응답 메시지를 설정해보자.

        • from django.http import JsonResponse
        • JsonResponse에 응답 메시지를 지정하여 return하면, 메시지가 Json형태로 보내진다.
        • 첫 번째 인자는 전달할 데이터로, 반드시 dictionary 객체여야 한다.
        • 두 번째 인자는 전달할 상태 코드를 지정하면 된다.
  • Client 요청(GET) 호출하기

    • 서버 열기: python manage.py runserver
    • 터미널 창을 추가하여 http GET localhost:8000/user 입력
    • 인자로 입력한 상태 코드가 status line에 출력된다.
    • 인자로 입력한 메시지가 body에 출력된다.
  • Client 요청(POST) 호출하기

    • http POST localhost:8000/~ 변수명=데이터 변수명=데이터 ... 입력
    • 변수명=데이터 형식으로 POST 요청의 body에 담을 item을 보낼 수 있다.
    • string이 아닌 데이터는 = 대신 := seperater를 사용한다.
      *모델의 필드값이 integer로 정의됐다면 HTTP 요청을 통해 전송되는 값도 inteager 형태여야 한다.
    • single quote을 이용해 list와 dictionary라는 것을 알려준다. 또한, double quote을 사용해 dictionary의 Key라는 것을 알립니다.
      http -v POST www.devzunky.com numbers:='[1, 2, 3]' me:='{"name":"zunky"}'
    • HTTPie는 JSON 데이터 타입을 지원하기 때문에, 호출 시 입력한 변수명=데이터는 아래의 예시처럼 JSON 데이터 형식으로 body에 담겨 해당 URL로 보내진다.
    • body에 담긴 JSON 데이터는 views.py 내부 post()data = json.loads(request.body)에 의해 key:value로 구성된 딕셔너리 타입 데이터로 사용할 수 있다.
    • 참고 사이트
    # httpie를 통한 POST 요청
    http POST localhost:8000/pet/dog dog_name=스누피  dog_age:=12 dog_owner=Jason
    
    # JSON형태의 body 데이터
    {
      "변수명":"데이터"
    }
  • 기타 내용 정리

    • brew install httpie —> 성공적으로 설치가 완료되면 터미널에 http 입력했을 경우 "http: error: ~" 메시지가 뜸
    • 터미널 창 분할 단축키: command + d
    • 다음 줄(line)에서 바로 insert모드로 전환(터미널 명령어): o
    • mysql에서 명령 입력이 불충분하여 화살표가 나오는 경우: 부족한 부분을 이어서 마저 입력하면 된다.
    • GET과 POST가 동시에 호출될 수는 없다.
    • views.py의 get메소드에서 매개 변수 request에 저장되는 값은??: client의 요청 정보가 request 변수에 저장된다.
    • 포트가 이미 사용 중이라는 error가 발생한 경우: sudo lsof -t -i tcp:8000 | xargs kill -9
    • .swp 파일이 생성됐을 시 해결 방법: ls -al —> .sap 파일을 명령어로 삭제해주면 된다.

# CRUD(2) 과제 관련 내용 정리

  • ForignKey의 on_deletemodels.CASCADE: 해당 옵션을 추가하면, 외래키 필드가 참조 중인 데이터(ForeingKeyField가 바라보는 값)가 삭제됐을 경우, 해당 데이터를 외래키 필드값으로 갖는 class 인스턴스(자식 테이블의 row)도 삭제된다.
  • ForignKey의 참조 테이블을 string형태로 입력하는 이유: 참조할 테이블(class 이름)을 변수 형태로 입력하는 것과 특별히 다르지 않다. 하지만, 다른 app의 models.py 내부 테이블을 참조하는 경우string형태로 참조할 테이블을 나타내야 한다.
    • production app 내부에서 정의된 Manufacturer 모델(class)을 참조
  • urls.py에서 HTTP 요청 url에 추가될 주소는 복수 형태(ex.'users')로 입력하는 것이 좋다.
  • data['name']'name'프론트엔드에서 전송하는 key값에 해당된다.
class OwnerView(view):
	def post(self, request):
    	data = json.loads(request.body)
    	Owner.objects.create(
            name = data['name']
            email = data['email']
            age = data['age']
        )
        return JsonResponse({'message':'SUCCESS'}, status=201)
  • views.py에서 Foreingkey 필드 데이터POST요청으로 생성하는 로직을 만드는 두 가지 방법
    • Foreingkey 필드에 대한 값으로 참조 테이블(바라보는 테이블)의 특정 '객체'를 할당
      • 외래키 필드명= Owner.objects.get(name=data['owner']))
    • Foreingkey 필드에 대한 값으로 참조 테이블의 특정 '객체의 데이터'를 할당
      • 외래키 필드의 db_column명'= Owner.objects.get(name=data['owner'].id))
    • 두 가지 방법 중 편한 걸 사용하면 된다.
    • 아래의 예시는 외래키 필드의 db_column명특정 객체의 데이터가 할당됐다.
class DogView(view):
    def post(self, request):
        data = json.loads(request.body)
        owner = Owner.objects.get(name=data['owner'])
    	Owner.objects.create(
            name = data['name']
            age = data['age']
            owner_id = owner.id  # db_column명 = 특정 객체의 데이터
        )
        return JsonResponse({'message':'SUCCESS'}, status=201)
  • views.py에서 변수명 짓는 방법
    • model 객체를 한 개만 가져오는 경우: '소문자 class 이름(단수 형태)`
    • model 객체를 여러 개만 가져오는 경우: '소문자 class 이름(복수 형태)`
    • model 객체를 활용하여 새로운 객체를 생성하는 경우: '소문자 class 이름_데이터 관련 단어` ex) owner_information
class OwnerView(view):
    def get(self, request):
        result = []
        owners = Owner.objects.all()
        
        for owner in owners:
            owner_information= {
                'name':owner.name,
                'email':owner.email,
                'age':owner.age,
            }
            
            result.append(owner_information)
        return JsonResponse({'result':result}, status=200)
  • 정방향 참조 vs 역방향 참조
    • Foreignkey field가 정의된 테이블(자식 테이블)에서 부모 테이블의 필드값접근하는 것을 뜻한다.(정방향)
      • 방법: 자식 테이블 객체.외래키 필드 이름.접근하려는 부모 테이블의 필드 이름
      • ex)Dog.objects.get(name='흰둥이').owner_id.name
    • 참조 대상 테이블(부모 테이블)에서 자식 테이블의 객체에 접근하는 것(역방향)
      • 방법: 부모 테이블 객체.자식 테이블 이름(소문자)_set.all()
      • 부모 테이블의 객체가 복수의 자식 테이블 객체참조하고 있을 수 있기 때문에 쿼리셋 형태로 데이터를 리턴한다.
      • ex) Owner.objects.get(name='james').dog_set.all()
      • all() 대신 filter()를 사용해 하나의 객체만을 가져오고 싶은 경우...
        • ex) Owner.objects.get(name='james').dog_set.filter(name='흰둥이').first().age
class OwnerView(view):
    def get(self, request):
        result = []
        owners = Owner.objects.all()
        
        for owner in owners:
            dogs = owner.dog_set.all()   # 역방향 참조로 복수의 데이터 객체를 가져옴
            dog_list = []
            for dog in dogs:
                dog_information = {
                   'name':dog.name,
                   'age':dog.age,
                }
                dog_list.append(dog_information)
            owner_information= {
                'name':owner.name,
                'email':owner.email,
                'age':owner.age,
                'dogs':dog_list
            }
            
            result.append(owner_information)
        return JsonResponse({'result':result}, status=200)

    
profile
Difference & Repetition

0개의 댓글