TIL44. Django : Django API with httpie

ID์งฑ์žฌยท2021๋…„ 10์›” 19์ผ
4

Django

๋ชฉ๋ก ๋ณด๊ธฐ
34/43
post-thumbnail

๐Ÿ“Œ ์ด ํฌ์ŠคํŒ…์—์„œ๋Š” Django ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ API ์„ค๊ณ„ํ•˜๊ณ , ์ด๋ฅผ Create, Readํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.



๐ŸŒˆ Django API with httpie

๐Ÿ”ฅ API ์ƒ์„ฑ ๋ฐ ์‚ฌ์šฉ๋ฒ• : POST

๐Ÿ”ฅ API ์ƒ์„ฑ ๋ฐ ์‚ฌ์šฉ๋ฒ• : GET

๐Ÿ”ฅ ๋ณด์™„ : List Comprehension ํ™œ์šฉํ•˜์—ฌ View ์ž‘์„ฑํ•˜๊ธฐ



1. API ์ƒ์„ฑ ๋ฐ ์‚ฌ์šฉ๋ฒ• : POST

๐Ÿค” ํด๋ผ์ด์–ธํŠธ ์ค€๋น„ํ•˜๊ธฐ

โœ”๏ธ Server์— HTTP request ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ์›น๋ธŒ๋ผ์šฐ์ €, Httpie, Postman ๋“ฑ์ด ์žˆ๋‹ค.

โœ”๏ธ Httpie ์„ค์น˜ ๋ฐฉ๋ฒ•์€ brew๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

$ brew install httpie

โœ”๏ธ httpie๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ POST ์š”์ฒญ(string type)์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํ•œ๋‹ค. path๋ฅผ ์ ์€ ๋’ค, key์™€ value๋ฅผ ๋งคํ•‘ํ•œ๋‹ค.

$ http -v POST 127.0.0.1:8000/[path] key1="value1" key2="value2" key3="value3"

๐Ÿค” models.py ์ƒ์„ฑํ•˜๊ธฐ

โœ”๏ธ POST ์š”์ฒญ์œผ๋กœ ์˜จ message body์˜ ๊ฐ’์„ DB์— ์ƒ์„ฑ(CREATE)ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ์„  models.py์— Table์„ ๋งŒ๋“ ๋‹ค.

โœ”๏ธ Dog ํ…Œ์ด๋ธ”์— owner ์ปฌ๋Ÿผ์€ ForeignKey๋กœ Owner ๋ชจ๋ธ์„ ์ฐธ์กฐ์‹œ์ผœ ์„œ๋กœ ๊ด€๊ณ„๋ฅผ ๋งบ์–ด์ค€๋‹ค.

from django.db import models
# ๐Ÿš€ Owner table
class Owner(models.Model):
    name = models.CharField(max_length=45)
    email = models.CharField(max_length=300)
    age = models.IntegerField()
    class Meta:
        db_table = "owners"
# ๐Ÿš€ Dog table        
class Dog(models.Model):
    name = models.CharField(max_length=45)
    age = models.IntegerField()
    owner = models.ForeignKey("Owner", on_delete=models.CASCADE)
    class Meta:
        db_table = "dogs"

๐Ÿค” Python์€ JSON ํ˜•์‹์„ ๋ฐ”๋กœ ์ดํ•ดํ•  ์ˆ˜ ์—†๋‹ค.

โœ”๏ธ Python์€ Dictํ˜• ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์žˆ์ง€๋งŒ, ๋ฐ”๋กœ JOSNํ˜•์‹์„ ์ดํ•ดํ•  ์ˆ˜ ์—†๋‹ค. ์ด์— HTTP Message์˜ body ๋ถ€๋ถ„์„ json.loads๋ฅผ ํ†ตํ•ด Dict๋กœ ๋ณ€ํ™˜์‹œ์ผœ Python์—์„œ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.

โœ”๏ธ ์ฒ˜๋ฆฌ ํ›„ ๋‹ค์‹œ JOSN ํ˜•์‹์œผ๋กœ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด JSONResponse ๋ชจ๋“ˆ์„ ์ด์šฉํ•œ๋‹ค.

โœ”๏ธ ์„ฑ๊ณต์„ ์˜๋ฏธํ•˜๋Š” Status Code ์ค‘, ์ƒ์„ฑ์€ 201๋ฒˆ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋‹ค.

โœ”๏ธ ์ฆ‰, JSONํ˜•์‹์˜ request๋ฅผ ๋ฐ›์•„์˜ฌ ๋•Œ๋Š” json.loads() ๋‹ค์‹œ JSONํ˜•์‹์œผ๋กœ response๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ๋Š” JsonResponse๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

import json
from django.http import JsonResponse
from django.views import View
from .models import Owner, Dog
# ๐Ÿš€ OwnerView controller
class OwnerView(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": "CREATED"}, status=201)
# ๐Ÿš€ DogView controller
class DogView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)
            Dog.objects.create(
                name=data["name"],
                age=data["age"],
                owner=Owner.objects.get(name=data["owner"]),
            )
        except KeyError:
            return JsonResponse({"MESSAGE": "IVALID_KEY"}, status=400)
        return JsonResponse({"MESSAGE": "CREATED"}, status=201)

๐Ÿค” Path๋Š” ์ž์›(Resource)์„ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋„๋ก ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

โœ”๏ธ ํด๋ผ์ด์–ธํŠธ๋Š” URI ํ†ตํ•ด ์„œ๋ฒ„์— ์š”์ฒญํ•˜๋Š”๋ฐ ์ด ๊ฒฝ๋กœ๋Š” ์ž์›์„ ์ •ํ™•ํžˆ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค. ํ–‰์œ„๋Š” ๋งค์„œ๋“œ(GET, POST..)๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ๋Œ€ํ•œ ์ž์›์„ ๋ช…ํ™•ํžˆ ๋‚˜ํƒ€๋‚ด๋Œ€๋ก URL๋ฅผ ์„ค๊ณ„ํ•ด์•ผ ํ•œ๋‹ค.

โœ”๏ธ ๋ฉ”์ธ urls.py์—์„œ owners ์•ฑ์˜ urls.py๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์œ„์ž„ํ•˜๋„๋ก include๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •ํ•œ๋‹ค.

from django.urls import path, include
urlpatterns = [
    path("", include("owners.urls")),
]

โœ”๏ธ OwnerView์™€ DogView์— ๋Œ€ํ•œ path๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ง€์ •ํ•ด์ค€๋‹ค.

from django.urls import path
from .views import OwnerView, DogView
urlpatterns = [
    path("owner/", OwnerView.as_view()),
    path("dog/", DogView.as_view()),
]

โœ”๏ธ ์ด์ œ key&value ํ˜•ํƒœ๋กœ Httpi ์š”์ฒญ(POST)์„ ๋ณด๋‚ด๋ฉด, MySQL์˜ DB์— ๊ฐ’์ด ์ €์žฅ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹จ, Controller๊ฐ€ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก urls.py์˜ path๋ฅผ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

$ http -v POST 127.0.0.1:8000/owner name="์žฅ์žฌ์›" age=33 email="jewon119@gmail.com"
$ http -v POST 127.0.0.1:8000/dog name="๋ณต์‹ค์ด" age=7 owner="์žฅ์žฌ์›"



2. API ์ƒ์„ฑ ๋ฐ ์‚ฌ์šฉ๋ฒ• : GET

๐Ÿค” ๋ฐ์ดํ„ฐ READ๋ฅผ ์œ„ํ•œ GET ๋งค์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

โœ”๏ธ HTTP ๋งค์„œ๋“œ๊ฐ€ POST๋กœ ์š”์ฒญ์˜ฌ ๋•Œ๋Š” ํ•ด๋‹น CBV(Class-based-View)์— post ๋งค์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ , GET ๋งค์„œ๋“œ๋กœ ์š”์ฒญ์˜จ๋‹ค๋ฉด CBV์— get ๋งค์„œ๋“œ๊ฐ€ ์ž‘๋™ํ•œ๋‹ค.

โœ”๏ธ DB์—์„œ ๋ฐ์ดํ„ฐ์™€ Dictํ˜•์œผ๋กœ ์ฒ˜๋ฆฌํ•œ ํ›„, ๊ฐ€๊ณตํ•œ ๋ฐ์ดํ„ฐ๋ฅผ JsonResponse์„ ์‚ฌ์šฉํ•ด JSONํ˜•์‹์œผ๋กœ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

import json
from django.http import JsonResponse
from django.views import View
from .models import Owner, Dog
# ๐Ÿš€ OwnerView controller
class OwnerView(View):
    def post(self, request): # ๐Ÿ‘ˆ POST ์š”์ฒญ์ผ ๋•Œ ์ž‘๋™
        ......์ƒ๋žต......
    def get(self, request): # ๐Ÿ‘ˆ GET ์š”์ฒญ์ผ ๋•Œ ์ž‘๋™
        owners = Owner.objects.all()
        result = []
        for owner in owners:
            dogs = owner.dog_set.all()
            dog_list = []
            for dog in dogs:
                dog_data = {
                    "name": dog.name,
                    "age": dog.age,
                }
                dog_list.append(dog_data)
            result.append(
                {
                    "name": owner.name,
                    "mail": owner.email,
                    "age": owner.age,
                    "my_dogs": dog_list,
                }
            )
        return JsonResponse({"MESSAGE": result}, status=200)
# ๐Ÿš€ DogView controller
class DogView(View):
    def post(self, request):
        ......์ƒ๋žต......
    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)

โœ”๏ธ ์ด์ œ ์•„๋ž˜์™€ ๊ฐ™์ด Httpi ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด, DB์—์„œ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์™€ JSONํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

$ http -v GET 127.0.0.1:8000/owner ๐Ÿ‘ˆ OwnerView์— get ๋งค์„œ๋“œ ์ž‘๋™
$ http -v GET 127.0.0.1:8000/dog ๐Ÿ‘ˆ DogView์— get ๋งค์„œ๋“œ ์ž‘๋™



3. ๋ณด์™„ : Comprehension ๋ฌธ๋ฒ• ํ™œ์šฉํ•˜์—ฌ View ์ž‘์„ฑํ•˜๊ธฐ

๐Ÿค” for๋ฌธ์„ ํ†ตํ•ด ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๋ณด๋‹ค Comprehension์ด ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค.

โœ”๏ธ Comprehension ๋ฌธ๋ฒ•์€ List, Dict, Tulple ๋“ฑ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , for๋ฌธ์„ ํ†ตํ•ด appendํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค.

import json
from django.http import JsonResponse
from django.views import View
from .models import Owner, Dog
# ๐Ÿš€ OwnerView controller
class OwnerView(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": "CREATED"}, status=201)
    def get(self, request): # ๐Ÿ‘ˆ 2์ค‘ List Comprehension
        result = [
            {
                "name": owner.name,
                "mail": owner.email,
                "age": owner.age,
                "my_dogs": [
                    {"name": dog.name, "age": dog.age} for dog in owner.dogs.all() # ๐Ÿ‘ˆ related_name ์‚ฌ์šฉ์œผ๋กœ "dogs"๋กœ ์—ญ์ฐธ์กฐ
                ],
            }
            for owner in Owner.objects.all()
        ]
        return JsonResponse({"MESSAGE": result}, status=200)
# ๐Ÿš€ DogView controller
class DogView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)
            Dog.objects.create(
                name=data["name"],
                age=data["age"],
                owner=Owner.objects.get(name=data["owner"]),
            )
        except KeyError:
            return JsonResponse({"MESSAGE": "IVALID_KEY"}, status=400)
        return JsonResponse({"MESSAGE": "CREATED"}, status=201)
    def get(self, request): # ๐Ÿ‘ˆ List Comprehension
        result = [
            {
                "name": dog.name,
                "age": dog.age,
                "owner": dog.owner.name,
            }
            for dog in Dog.objects.all()
        ]
        return JsonResponse({"MESSAGE": result}, status=200)
profile
Keep Going, Keep Coding!

0๊ฐœ์˜ ๋Œ“๊ธ€