TIL27 | Django C.R.U.D : URLconf, Model, View

2021. 10. 20. 13:44언어/Python

반응형

Django C.R.U.D 과제

목표

  1. URLconf, View를 활용하여 리스트를 표출하는 엔드포인트 작성하기

  2. 엔드포인트의 결과로 return 할 JSON data 만들기

  3. httpie를 이용해 GET/POST 요청 보내기

Modeling

  • 주인과 강아지

 

django_workflow

 

URLconf 설정

  1. 최상위 urls.py 파일에 app 경로를 추가

    master/urls.py

    from django.urls import path, include
    
    urlpatterns = [
        path('', include('owners.urls')),
    ]
  2. owners app에 urls.py 생성

  3. app의 urls.py 파일에 view class 경로 추가

    owners/urls.py

    from django.urls import path
    from owners.views import OwnersView, DogsView
    
    urlpatterns = [
        path('owners', OwnersView.as_view()),
        path('dogs', DogsView.as_view()),
    ]
    '''
    Owners
    http -v POST 127.0.0.1:8000/owners name='홍길동' email='abc123@naver.com' age=25
    http -v GET 127.0.0.1:8000/owners
    
    Dogs
    http -v POST 127.0.0.1:8000/dogs name='아롱' age=25 owner_id=1
    http -v GET 127.0.0.1:8000/dogs
    '''

 

Model

Model 테이블 구조

과제1  owner ERD

 

Models.py 작성

models.py에 Model Class작성을 통해 Database의 테이블과 mapping

owners/models.py

from django.db import models

class Owner(models.Model):
    name     = models.CharField(max_length=45)
    email    = models.CharField(max_length=300)
    age      = models.IntegerField(default=0)
    class Meta:
        db_table = 'owners'


class Dog(models.Model):
    name     = models.CharField(max_length=45)
    age      = models.IntegerField(default=0)
    owner    = models.ForeignKey("Owner", on_delete=models.CASCADE)
    class Meta:
        db_table = 'dogs'

models.py 작성한 내용 DB에 적용

# 1. makemigrations : migration 파일만들기
python manage.py makemigrations app이름

# 2. migrate : makemigrations으로 생성한 migration파일을 database에 적용
python manage.py migrate

 

View

POST / GET method 설계

POST 신규 주인 등록

  • def post(self, request) 함수

    def post(self, request): 
            '''
            함수의 목적 : client의 주인 등록 요청에 맞게 database에 주인 정보 생성
    
            1. Input : Owner 데이터(json)
            2. Output : 주인정보 등록 여부
                    case1) json response : { 'message' : 'SUCCESS'}    
                    case2) http response : 200
            3. How : Input으로 들어온 주인 데이터를 ORM을 이용해서 해당 Database의 Owner테이블에 데이터 저장.
                    (1) json data -> python dictionary 변환
                        {
                            'name' : '제임스',
                            'age': 20,
                            'email' : '@example.com'
                        }
                    (2) Owner.objects.create(Input 데이터)
                    (3) return {'message' : 'SUCCESS'} -> json data 변환 후 반환
            ''' 
            return HttpResponse(201)

GET 주인 리스트 : 이름, 이메일, 나이

  • def get(self, request) 함수

    def get(self, request):
            # Client의 요청을 처리할 수 있는 로직
            '''
            함수의 목적 : client의 주인정보 요청에 맞게 database에 주인 정보 호출 및 가공 후 데이터 반환
    
            1. Input : 
            2. Output : 주인 목록
                        result = [
                             {
                                 'id' : 1,
                                 'name' : '제임스',
                                 'age' : 20,
                                 'email' : '@example.com'
                             }
                         ]
            3. How : Owner테이블 데이터 조회. Owner Instance 들을 python의 native한 data type인 dictionary로 변환해줘야 한다.
                    (1) owners = Owner.objects.all()
                       (2) for문으로 owner instance를 하나씩 추출해서 반환
            ''' 
            return HttpResponse(200)

 

Views.py 작성 👉️ Refactoring 진행

owners/views.py

import json # json.loads()

from django.http import JsonResponse # JsonResponse() : json 형태로 응답 보내기
from django.views import View

from owners.models import Owner, Dog

class OwnersView(View):
    def post(self, request):
        '''
        :: request params 
        Django가 요청을 받으면 Body의 json 데이터를 request객체 안에 담아서 보내준다.(request.body)
        request.body는 json형태이기 때문에 json.loads()함수를 사용해서 dictionary로 변환한다.
        '''
        data = json.loads(request.body)
        Owner.objects.create(
            name     = data['name'],
            email    = data['email'],
            age      = data['age'],
        )
        return JsonResponse({'Message': 'CREATED'}, status=201)


    def get(self, request):
        owners = Owner.objects.all()
        results = []
        for owner in owners:
            dogs = list(Dog.objects.values('name', 'age').filter(owner=owner.id))
            results.append(
                {
                    'name': owner.name,
                    'email' : owner.email,
                    'age': owner.age,
                    'dogs': dogs,
                }
            )
        return JsonResponse({'results': results}, status=200)

 

Views.py 작성

✨️ Refacoring ✨️

1️⃣️ Create() 예외 처리(try-except 구문)

2️⃣️ 이중 for문은 2nd list comprehension 으로 변경하기.

  • for문보다 list comprehension이 내부적으로 더 빠르게 동작한다.
  • values() 는 복잡하거나 대량의 데이터를 컨트롤 해야할 때 N+1 Problem 이 발생할 수 있으므로 지양한다.
    (Django ORM 최적화 공부하면서 다시 알아보기)

owners/views.py

import json

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

from owners.models import Owner, Dog

class OwnersView(View):
    # ORM create()에 try-except 구문 추가
    def post(self, request):
        data = json.loads(request.body)
        try:
            Owner.objects.create(
                name     = data['name'],
                email    = data['email'],
                age      = data['age'],
            )
            return JsonResponse({'message': 'CREATED'}, status=201)
        except KeyError:
            return JsonResponse({'error_message': 'KEY_ERROR'}, status=400)

    def get(self, request):
        # for문 + ORM values() 사용 => 2nd list comprehension으로 변경
        results = [ 
                    {
                        'name' : owner.name, 
                        'email': owner.email, 
                        'age'  : owner.age, 
                        'dogs' : [{'name': dog.name} for dog in owner.dogs.all()] 
                    }
                    for owner in Owner.objects.all()
                ]

        return JsonResponse({'results': results}, status=200)

 

Httpie 호출 결과

과제1  httpie 호출결과(GET 요청)

 

반응형