Python3 및 Django REST 프레임워크를 사용하여 API를 효율적으로 개발

이 강좌의 목표는api를 만들어서 구독자를 만들고 열거하는 것입니다.
이 강좌에서 우리는 데이터, 모델 만들기, 서열화 프로그램과 보기를 검사하고, 창설과 대량 창설 사이의 시간차를 계산하며, 조회 집합을 필터하는 방법을 배울 것이다.
우리가 사용할 유명 라이브러리는 DjangoDjango REST framework를 포함한다.
  • Installing libraries
  • Creating a Django project and app
  • Project structure
  • Understanding the data
  • Creating models
  • Creating serializers
  • Creating views
  • Creating routes (urls)
  • Adding a command for test data
  • Creating a bulk serializer
  • Queryset filtering

  • Django 및 Django REST 프레임워크 설치pip3 install django djangorestframework
    Django 프로젝트 및 Django 응용 프로그램 만들기

  • django 프로젝트를 위한 작업 디렉터리 만들기
    mkdir django_api_tutorial && cd django_api_tutorial
    

  • django 프로젝트 만들기
    django-admin startproject api .
    

  • 구독자를 위한django 프로그램 만들기
    python3 manage.py startapp subscribers
    

  • 구독 서버와 rest framework 응용 프로그램을 api/settings.py의 API 설정에 연결
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',         # new (djangorestframework)
        'subscribers'             # new
    ]    
    
    페이지 목록 결과의 설정 밑에 다음 내용을 추가합니다
    REST_FRAMEWORK = {
       'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
       'PAGE_SIZE': 32
    }
    

  • 프로젝트 구조
    ./django_api_tutorial
    │   manage.py
    │   README.md
    │
    ├───api
    │       asgi.py
    │       settings.py
    │       urls.py
    │       wsgi.py
    │       __init__.py
    │
    ├───data
    │       fake_users.csv
    │
    └───subscribers
        │   admin.py
        │   apps.py
        │   models.py
        │   serializers.py
        │   tests.py
        │   urls.py
        │   views.py
        │   __init__.py
        │
        ├───management
        │   └───commands
        │           bulktestdata.py
        │           testdata.py
        │
        └───migrations
                __init__.py
    
    django 프로젝트 구조에 대한 더 많은 정보here.

    데이터 이해
    다음은 본 강좌의 10행 가짜 데이터입니다.이 데이터는 Mockaroo로 만들어졌습니다.
    성함
    성.
    전자 우편
    성별 명사
    도시.
    컨디션
    모함메드
    포드
    [email protected]
    남성.
    워터타운
    매사추세츠 주
    브리안나
    리델
    [email protected]
    여성.
    인디애나폴리스
    인디애나 주
    주디
    파딩턴
    [email protected]
    남성.
    브로커턴
    매사추세츠 주
    칼리
    월드컵
    [email protected]
    여성.
    리즈만
    버지니아
    은혜에 감사하다
    피크포드
    [email protected]
    남성.
    뉴와크
    뉴저지 주
    베세니
    맥콜럼
    [email protected]
    여성.
    에반스웰
    인디애나 주
    엘시
    회릴
    [email protected]
    여성.
    렉싱턴
    켄터키 주
    캐린
    하티르
    [email protected]
    여성.
    콜롬비아 대학
    사우스 캐롤라이나
    랑니
    엘리엇
    [email protected]
    남성.
    조리트
    일리노스
    켈리안
    켈소
    [email protected]
    여성.
    성 베나디노
    캘리포니아 주
    현재 우리는 이 열의 매 열을 그것들의 상응하는 데이터 형식으로 분해할 것이다.
    first_name      VARCHAR(64)
    last_name       VARCHAR(64)
    email           TEXT
    gender          VARCHAR(8)
    city            VARCHAR(256)
    state           VARCHAR(24)
    
    이러한 변수를 어떻게 처리하는지 이해하면 우리는 모델과 서열화 프로그램을 쉽게 만들 수 있을 것이다.

    모델 생성하기
    모델 정의는 subscribers/models.py.
    from django.db import models
    
    class Location(models.Model):
        city = models.CharField(null=False, max_length=256)
        state = models.CharField(null=False, max_length=64)
    
    class Subscriber(models.Model):
        first_name = models.CharField(null=False, max_length=64)
        last_name = models.CharField(null=False, max_length=64)
        email = models.TextField()
        gender = models.CharField(null=False, max_length=8)
        location = models.ForeignKey(Location, related_name='subscriber_location', on_delete=models.DO_NOTHING)
    
    위에서 우리는 구독자와 위치의 모델을 정의했다.
    구독자 모델과 위치 모델은 다대일의 관계이다. 왜냐하면 우리는 한 위치에 여러 명의 구독자가 있을 수 있기 때문이다.

    시리얼화된 프로그램 만들기
    현재 우리는 모델을 위해 서열화 프로그램을 정의할 것이다.이것은 API 응답을 얻기 위해 모델 대상을 json 대상으로 쉽게 변환할 수 있도록 합니다.
    시리얼화된 프로그램을 만들 때 Django REST 프레임워크를 사용하여 API에 많은 기능을 쉽게 추가할 수 있습니다.
    서열화 프로그램은 subscribers/serializers.py에서 정의됩니다.Subscriber Serializer에서create 메서드를 덮어써야 합니다.
    이것은 관계 모델을 사용할 때 정상적이다.
    from rest_framework import serializers
    
    class LocationSerializer(serializers.Serializer):
        city = serializers.CharField(required=True, max_length=256)
        state = serializers.CharField(required=True, max_length=64)
    
        class Meta:
            fields = ['city', 'state']
    
    class SubscriberSerializer(serializers.Serializer):
        id = serializers.IntegerField(required=False)
        created = serializers.DateTimeField(required=False)
        first_name = serializers.CharField(required=True, max_length=64)
        last_name = serializers.CharField(required=True, max_length=64)
        email = serializers.CharField(required=False)
        gender = serializers.CharField(required=True, max_length=8)
        location = LocationSerializer(required=True)
    
        class Meta:
            fields = ['first_name', 'last_name', 'email', 'gender', 'location']
            read_only_fields = ['id', 'created']
    
        def create(self, validated_data):
            # remove location from serialized data and add model object
            location = validated_data.pop('location')
            city = location.get('city', None)
            state = location.get('state', None)
    
            if not city and not state:
                raise serializers.ValidationError('No location input found')
    
            # call get or create to reuse location objects
            location_obj = Location.objects.get_or_create(city=city, state=state)[0]
            # add location back to validated data
            validated_data.update({'location': location_obj})
    
            # unpack validated_data to create a new Subscriber object
            return Subscriber.objects.create(**validated_data)
    
    
    우리는 이미 서열화 프로그램을 정의했기 때문에 모델에서 쉽게 창설, 읽기, 업데이트, 삭제, 열거 대상을 만들 수 있다.
    우리가 이러한 관점을 실시할 때, 우리는 이 점을 보게 될 것이다.

    뷰 생성하기
    뷰는 subscribers/views.py에 정의되어 API 사용자가 사용할 수 있는 기능을 포함합니다.
    이 강좌에서 구독자를 만들고 열거하는 방법을 중점적으로 소개하지만, 데이터를 추가하는 동시에 데이터를 쉽게 삭제하는 방법이 필요할 수도 있습니다.
    다음 예제에서는 Django REST 프레임워크 mixins를 사용하여 API에 삭제 작업을 쉽게 추가하는 방법을 보여 줍니다.
    from rest_framework import viewsets, mixins
    
    from .models import Subscriber
    from .serializers import SubscriberSerializer
    
    class SubscriberView(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin):
        queryset = Subscriber.objects.all()
        serializer_class = SubscriberSerializer
    
    위의 간단한 보기는 구독자에게 목록과 생성 기능이 있는 일반적인 API 인터페이스를 제공합니다.
    다음과 같이 삭제 방법 및 기능을 쉽게 추가할 수 있습니다.
    from rest_framework import viewsets, mixins
    
    from .models import Subscriber
    from .serializers import SubscriberSerializer
    
    class SubscriberView(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin,
                         mixins.DestroyModelMixin):
        queryset = Subscriber.objects.all()
        serializer_class = SubscriberSerializer
    
    유일한 새로운 변화는 클래스 정의에 추가된 것입니다 mixins.DestroyModelMixin.믹인에 대한 자세한 내용은 Django REST 프레임워크docs에서 확인할 수 있습니다.

    라우팅 작성
    이제 API로 이동할 수 있도록 URL을 추가해야 합니다.URL은 subscribers/urls.py에 정의되어 있습니다.
    우리는 또한 기초 API가 구독자로부터 경로를 찾았는데, 이것은 api/urls.py 에서 정의된 것이다.
    # api/urls.py
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('tutorial/', include('subscribers.urls'))
    ]
    
    # subscribers/urls.py
    from rest_framework import routers
    
    from .views import SubscriberView
    
    router = routers.DefaultRouter(trailing_slash=False)
    router.register(r'subscribers', SubscriberView, basename='subscribers')
    urlpatterns = router.urls
    
    구독 서버 URL에서는 Django REST 프레임워크의 라우터를 사용하여 뷰에 정의된 모든 기능을 쉽게 추가할 수 있습니다.
    뷰포트가 있는 라우터는 API에 대해 다음 라우트를 활성화합니다.
    GET     /tutorial/subscribers       List view of subscribers
    POST    /tutorial/subscribers       Create a new subscriber
    

    데이터 테스트 명령 추가
    이제 테스트 데이터를 API에 쉽게 추가할 수 있도록 django에 명령을 추가합니다.이 명령들은 subscribers/management/commands에서 정의되고 첫 번째 명령은 testdata.py이다.
    import csv
    
    from time import time
    from django.core.management.base import BaseCommand, CommandError
    
    from subscribers.serializers import SubscriberSerializer
    
    class Command(BaseCommand):
        help = 'Adds the fake test data to the API'
    
        def handle(self, *args, **options):
            try:
                with open('data/fake_users.csv', 'r') as fin:
                    csvreader = csv.reader(fin)
                    headers = next(csvreader)
                    data = [{'first_name': row[0],
                             'last_name': row[1],
                             'email': row[2],
                             'gender': row[3],
                             'location': {'city': row[4], 'state': row[5]}
                             } for row in csvreader
                            ]
                    # time how fast it takes to add all records 1 by 1
                    start = time()
                    for item in data:
                        serializer = SubscriberSerializer(data=item)
                        if serializer.is_valid():
                            serializer.create(item)
                    stop = time()
                    print(f'{len(data)} items added in {stop-start} seconds')
            except FileExistsError:
                raise CommandError('No testdata found')
    
    이 명령은 API에 테스트 레코드를 추가합니다.기록 수량과 추가 속도도 추적합니다.
    우리는 이 명령을 실행하고 출력이 무엇인지 볼 것이다.
    python3 manage.py testdata
    
    출력: 6000 items added in 31.6553955078125다음에 우리는 대용량 서열화 프로그램을 실현하고 새로운 대용량 명령을 추가해서 기록을 만드는 속도를 높일 수 있는지 확인할 것이다.

    대량 서열화 프로그램 만들기
    우리는 한 번에 여러 개의 대상을 만들 뿐만 아니라, 하나하나 대상을 만들 필요가 없는 대량 서열화 프로그램을 만들 것이다.
    class BulkSubscriberSerializer(serializers.Serializer):
        subscribers = SubscriberSerializer(many=True)
    
        class Meta:
            fields = ['subscribers']
    
        def create(self, validated_data):
            # store the Subscriber objects to be created in bulk
            create_objects_list = []
            # iterate over the validated_data and add Subscriber objects to a list to be created
            for data in validated_data:
                # notice the same functionality from the regular serializer
                location = data.pop('location')
                city = location.get('city', None)
                state = location.get('state', None)
                location_obj = Location.objects.get_or_create(city=city, state=state)[0]
                # combine data and {'location': location_obj} and unpack to the Subscriber model
                create_objects_list.append(Subscriber(**{**data, **{'location': location_obj}}))
            return Subscriber.objects.bulk_create(create_objects_list)
    
    bulktestdata 라는 새 명령을 만들 것입니다. 이 명령은 subscribers/management/commands/bulktestdata.py 에서 정의됩니다.
    이것은 대량 서열화 프로그램을 사용하여 기록을 추가하고 필요한 시간을 추적할 것입니다.
    import csv
    
    from time import time
    from django.core.management.base import BaseCommand, CommandError
    
    from subscribers.serializers import BulkSubscriberSerializer
    
    class Command(BaseCommand):
        help = 'Adds the fake test data to the API'
    
        def handle(self, *args, **options):
            try:
                with open('data/fake_users.csv', 'r') as fin:
                    csvreader = csv.reader(fin)
                    headers = next(csvreader)
                    data = [{'first_name': row[0],
                             'last_name': row[1],
                             'email': row[2],
                             'gender': row[3],
                             'location': {'city': row[4], 'state': row[5]}
                             } for row in csvreader
                            ]
                    # time how fast it takes to add records in bulk
                    start = time()
                    bulk_serializer = BulkSubscriberSerializer(data={'subscribers': data})
                    if bulk_serializer.is_valid():
                        bulk_serializer.create(data)
                    stop = time()
                    print(f'{len(data)} items added in {stop-start} seconds')
            except FileExistsError:
                raise CommandError('No testdata found')
    
    이제 새 명령을 실행할 때 모든 기록의 추가 속도를 봅시다.
    python3 manage.py bulktestdata
    
    출력: 6000 items added in 5.3229029178619385 seconds마지막으로, 우리는 루트에 전송된 데이터에 따라 보기를 업데이트하여 일반적인 프로그램이나 대량 서열화 프로그램을 사용할 것입니다.
    from rest_framework import viewsets, mixins
    from rest_framework.response import Response
    
    from .models import Subscriber
    from .serializers import SubscriberSerializer, BulkSubscriberSerializer
    
    class SubscriberView(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin,
                         mixins.DestroyModelMixin):
        queryset = Subscriber.objects.all()
        serializer_class = SubscriberSerializer
    
        def create(self, request, *args, **kwargs):
            # if the data is a dictionary, use parent create that relies on serializer_class
            if isinstance(request.data, dict):
                return super(SubscriberView, self).create(request, *args, **kwargs)
            # if the data is a list, send to the bulk serializer to handle creation
            elif isinstance(request.data, list):
                serializer = BulkSubscriberSerializer(data={'subscribers': request.data})
                if serializer.is_valid():
                    serializer.create(request.data)
                    return Response(serializer.data, status=201)
                else:
                    return Response(serializer.errors, status=400)
            else:
                return Response('Invalid data received', status=400)
    
    이제 API는 한 번에 일대다 레코드를 생성하고 사용자가 현재 구독 서버를 탐색할 수 있도록 합니다.
    다음은 API 쌍http://127.0.0.1:8000/tutorial/subscribers의 GET 요청에 대한 응답 세션입니다.
    {
        "count": 6000,
        "next": "http://127.0.0.1:8000/tutorial/subscribers?page=2",
        "previous": null,
        "results": [
            {
                "id": 1,
                "created": "2020-10-13T15:51:50.850563Z",
                "first_name": "Mohammed",
                "last_name": "Poad",
                "email": "[email protected]",
                "gender": "Male",
                "location": {
                    "city": "Watertown",
                    "state": "Massachusetts"
                }
            },
            {
                "id": 2,
                "created": "2020-10-13T15:51:50.862560Z",
                "first_name": "Briana",
                "last_name": "Liddall",
                "email": "[email protected]",
                "gender": "Female",
                "location": {
                    "city": "Indianapolis",
                    "state": "Indiana"
                }
            },
            ...
        ]
    }
    

    조회 세트 필터
    우리는 모든 구독자를 쉽게 열거할 수 있지만, 만약 우리가 특정주에서 온 구독자만 보고 싶다면?
    현재, 사용자로서, 우리는 API에서 모든 구독자를 추출하고, 우리의 결과를 필터해야 한다.
    이것이 바로 Django의queryset 필터가 사용자가 더 많은 제어를 얻을 수 있도록 도와줄 수 있는 곳입니다.
    사용자는 요청에 조회 파라미터를 보낼 수 있으며, 우리는 그것을 사용하여 결과를 필터할 수 있다.새 뷰는 다음과 같습니다.
    from rest_framework import viewsets, mixins
    from rest_framework.response import Response
    
    from .models import Subscriber
    from .serializers import SubscriberSerializer, BulkSubscriberSerializer
    
    class SubscriberView(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin,
                         mixins.DestroyModelMixin):
        serializer_class = SubscriberSerializer
    
        def get_queryset(self):
            queryset = Subscriber.objects
            if 'state' in self.request.query_params:
                queryset = queryset.filter(location__state__icontains=self.request.query_params['state'])
            return queryset.order_by('created')
    
    
        def create(self, request, *args, **kwargs):
            # if the data is a dictionary, use parent create that relies on serializer class
            if isinstance(request.data, dict):
                return super(SubscriberView, self).create(request, *args, **kwargs)
            # if the data is a list, send to the bulk serializer to handle creation
            elif isinstance(request.data, list):
                serializer = BulkSubscriberSerializer(data={'subscribers': request.data})
                if serializer.is_valid():
                    serializer.create(request.data)
                    return Response(serializer.data, status=201)
                else:
                    return Response(serializer.errors, status=400)
            else:
                return Response('Invalid data received', status=400)
    
    우리는 get_queryset 방법을 추가했습니다. 현재 GET 요청에서 조회 매개 변수로 발송할 수 있습니다. state예를 들어 http://127.0.0.1:8000/tutorial/subscribers?state=Texas에 GET 요청을 보내면 전체 결과가 더 적다는 것을 알 수 있습니다.
    {
        "count": 629,
        "next": "http://127.0.0.1:8000/tutorial/subscribers?page=2&state=Texas",
        "previous": null,
        "results": [
            {
                "id": 13,
                "created": "2020-10-13T19:51:29.461522Z",
                "first_name": "Laure",
                "last_name": "Chitter",
                "email": "[email protected]",
                "gender": "Female",
                "location": {
                    "city": "Corpus Christi",
                    "state": "Texas"
                }
            },
            ...
        ]
    }
    
    유효 부하를 기반으로 한 쌍의 다중 구독자를 만들고 모든 구독자를 열거하며 특정 상태의 구독자를 열거할 수 있는 API가 생겼습니다.
    이 강좌를 좋아하셨으면 좋겠습니다. 모든 코드를 찾을 수 있습니다. here

    좋은 웹페이지 즐겨찾기