TIL - Wecode | django- C.R.U.D 2

한성봉·2021년 5월 26일
3

django- C.R.U.D 2

다음 과제를 풀어보자.

다음 테이블을 만들고
POST

각 기능을 서로 다른 클래스로 구현해주세요.

  1. 신규 주인 등록
  2. 강아지 등록 (주인정보 필요)

위 기능을 구현 후 직접 httpie 를 활용하여 주인 2명의 정보와 각 주인 당 2~3마리의 강아지 정보를 데이터베이스에 저장해주세요.

GET

각 기능을 서로 다른 클래스로 구현해주세요.

  1. 주인 리스트
    • 이름, 이메일, 나이 포함
  2. 강아지 리스트
    • 이름, 나이, 주인 이름 포함
  3. 주인 리스트 (1번 코드에 추가)
    • 이름, 나이 포함, 키우는 강아지 리스트 (이름, 나이 포함)

urls.py (path 설정)

이번에는 실제 데이터를 요청받았을 때 httpie를 이용해서 POST, GET을 이용해서 데이터를 입력해보고 요청받은 데이터를 출력해보자..

프로젝트를 위한 기초세팅은 똑같다.

이후 우리는 owners라는 app을 하나 만들 것이다. owners라는 app을 만들면 안에 장고 기능을 가진 폴더가 생성된다.

client로 부터 데이터 요청을 받으면 우선 제일 부모 폴더에 있는 urls.py로 받는다.

# urls.py
from django.urls import path, include

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

여기가 부모 urls.py 이다. 여기는 server로 오는 요청을 경로를 처리하는 파일이라고 생각하면 된다.

localhost:8000/owners

위의 경로로 owners app을 사용하겠다는 요청이 오면 다시 상세 app으로 보내주는 역할을 한다. 그 역할을 하는 것이 바로 include 이다. 그러면 그 해당 app 의 urls.py로 보내준다.

근데 처음 startapp 으로 app 을 생성했을 때 urls.py는 존재하지 않는다. 그렇기 때문에 owners app 안에 새로 생성해줘여한다.

그 안에 다시 경로지정과 쓸 기능을 import 해줘야한다.

# owners.urls.py
from django.urls import path
from owners.views import OwnerListView, DogListView

urlpatterns = [
    path('/owners', OwnerListView.as_view()),
    path('/dogs', DogListView.as_view())
]

OwnerListView, DogListViewview.pyget, post 기능을 수행하는 코드를 작성하는 파일에서 클래스를 import해온다.
as_view는 중요한 함수이다. 해당 경로까지 온 요청이 어떤 method인지 판단해주는 함수이다.

우리는 여기까지 경로 설정을 마치고 본격적으로 views.py에 method를 실행할 기능을 구현해줘여한다.


views.py

1. client 준비

  • httpie 설치
brew install httpie

httpie 는 python 으로 개발된 콘솔용 http client 유틸리티로 curl 대신 http 개발 및 디버깅 용도로 사용 가능하며 다음과 같은 특징이 있다.

  • curl 에 비해 사용이 쉬움
  • json 지원 기능 내장
  • 출력을 포맷팅하여 보여주므로 가독성이 뛰어남
  • Form 과 file 업로드가 쉬움
  • HTTP 인증 및 커스텀 헤더 설정등

2. create
자원(resource)를 생성할 때, http method 중에 post method를 사용합니다. 또한 로그인 회원가입 등 중요한 정보도 POST method로 데이터를 request의 body에 담아서 client에서 server로 요청합니다.

models.py 에 클래스를 만들어서 테이블를 넣어줍니다.

  • models.py 테이블 class 작성
# models.py
class Owner(models.Model):
    name = models.CharField(max_length=50)
    email = models.CharField(max_length=300)
    age = models.IntegerField(null=True)

    class Meta:
        db_table: 'owners'


class Dog(models.Model):
    name = models.CharField(max_length=50)
    age = models.IntegerField(null=True)
    owner = models.ForeignKey('Owner', on_delete=models.CASCADE)

    class Meta:
        db_table: 'dogs'

models.py 에 기본 테이블을 만드는 클래스를 작성하였다. 이후 마이그레이션을 통해 테이블을 생성하면 된다.

지금부터 views.py 에 메소드 요청을 받는 기능을 구현해보자.

우선 json 을 import해와야한다. 그 이유는 파이썬에서 API로부터 JSON데이터를 받아와서 활용하기 쉬운 형태로 받아옴. 받아온 데이터를 json 형태로 Django의 view로 전달함. view는 다시 받아온 json 데이터를 template의 html 파일로 전달함. 템플릿으로 전달된 json 데이터는 자바스크립트에 의해 활용할 수 있는 형태로 다시 받아온다. 이제 자바스크립트를 통해서 json 데이터를 자유롭게 사용할 수 있다.

  • import 목록
# views.py
import json

from django.http import JsonResponse
from django.views import View
from .models import Owner, Dog
  • class 구현 (POST)
# views.py
class OwnerListView(View):
    def post(self, request):
        data = json.loads(request.body)
        Owner.objects.create(name=data['name'],
                             email=data['data'],
                             age=data['age'])
    return JsonResponse({'MESSAGE':'SUCCESS'}, status=201)
# views.py
class DogListView(View):
    def post(self, request)
        data = json.loads(request.body)
        Dog.objects.create(name=data['name'],
                           age=data['age'],
                           owner=Owner.objects.get(name=data['owner'])
                           )

이후 터미널에서 httpie 패키지를 이용해 데이터 요청을 해보자.
POST 메서드를 이용하는 명령어는 shell에서 명령하면 된다.

http POST localhost:8000/owners/owners name='철수' email='culsu@gmail.com' age=20
http POST localhost:8000/owners/owners name='상현' email='sanghyun@gmail.com' age=30

다음과 같이 데이터가 잘 입력된 것을 볼 수 있다.
우리는 name, email, age 값을 받는 클래스를 만들었다 앞의 세 개의 키값 중 한개라도 없이 요청한다면 어떤 결과가 나올까?

바로 KeyError가 출력된다. 해당하는 키값을 찾을 수 없다는 에러다. 찾고 싶은 키가 없다면 제일 앞부터 찾아서 에러를 출력한다.

그렇기 때문에 우리는 에러의 예외를 정의해야한다.

  • try, except
# views.py
class OwnerListView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)
            Owner.objects.create(name=data['name'],
                                 email=data['email'],
                                 age=data['age'])
        except KeyError:
            return JsonResponse({'MESSAGE': 'IVALID_KEY'}, status=400)
        return JsonResponse({'MESSAGE': 'SUCCESS'}, status=201)

except의 다음에 어떠한 에러인지 정의하지 않는다면 우리는 어디서 무슨 에러가 나든 except 하기 때문에 정확한 에러를 파악하기 힘들다.

Dog 클래스도 같은 로직으로 데이터를 POST하면 되겠다.!!

3.read
자원(resource)를 읽어 올 때, http method 중에 GET method를 사용합니다.

  • class 구현 (GET)
# views.py
class OwnerListView(View):
    def get(self, request):
        owners = Owner.objects.all()
        result = []

        for owner in owners:
            dogs = owner.dog_set.all()
            dog_list = []

            for dog in dogs:
                dogs = owner.dog_set.all()
                dog_info = (
                    {
                        'name': dog.name,
                        'age': dog.age
                    }
                )
                dog_list.append(dog_info)
            result.append(
                {
                    'name': owner.name,
                    'age': owner.age,
                    'email': owner.email,
                    'my_dog': dog_list
                }

            )

        return JsonResponse({'result': result}, status=200)
# views.py
class DogListView(View):
    def get(self, request):
        dogs = Dog.objects.all()
        
        result = []
        for dog in dogs:
            result.append(
            {
              'name': dog.name,
              'age': dog.age,
              'owner': dog.owner.name
            }
          )
        return JsonResponse({'MESSAGE': result}, status=200)

GET 요청

http -v GET localhost:8000/owners/owners
{
    "result": [
        {
            "age": 20,
            "email": "culsu@gmail.com",
            "my_dog": [
                {
                    "age": 5,
                    "name": "삽살이"
                },
                {
                    "age": 3,
                    "name": "보풀이"
                }
            ],
            "name": "철수"
        },
        {
            "age": 30,
            "email": "sanghyun@gmail.com",
            "my_dog": [
                {
                    "age": 4,
                    "name": "후치"
                },
                {
                    "age": 10,
                    "name": "희동이"
                }
            ],
            "name": "상현"
        }
    ]
}

원하는 데이터가 잘 출력된다.

0개의 댓글