Django REST framework学習紀要Tutorial 1 Serialization

13596 ワード

に頼る
  • Python 3.6.3[Python(2.7,3.2,3.3,3.4,3.5,3.6)どちらでもよい]
  • Django 1.11.7[Django(1.10,1.11,2.0 alpha)どちらでもよい]
  • 仮想環境のインストール、作成、構成
  • 仮想環境Pythonバージョン管理ツールPyenvのインストールと使用
  • 仮想環境の作成
  • mkdir django_rest_framework && cd django_rest_framework
    pyenv virtualenv 3.6.3 django_rest_framework
    pyenv local django_rest_framework
    
  • 関連パッケージ
  • をインストール
    pip install django djangorestframework
    pip install pygments  #       ,        
    

    Djangoプロジェクト初期化
  • tutorialプロジェクトとsnippetsアプリケーション
  • を作成する.
    django-admin startproject tutorial
    cd tutorial/
    
    python manage.py startapp snippets
    
  • snippetsアプリケーションおよびrest_frameworksettings.pyINSTALLED_APPSに追加する(Djangoバージョンが1.9未満の場合、snippets.apps.SnippetsConfigsnippetsに置き換える必要がある)
  • .
    INSTALLED_APPS = (
        ...
        'rest_framework',
        'snippets.apps.SnippetsConfig',
    )
    

    Modelの作成
    コードフラグメントを格納するためにSnippetモデルを作成する必要があります.
  • 修正snippets/models.pyファイル
  • from django.db import models
    from pygments.lexers import get_all_lexers
    from pygments.styles import get_all_styles
    
    #     pygments              
    LEXERS = [item for item in get_all_lexers() if item[1]]
    #     pygments         
    LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
    #     pygments            
    STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
    
    
    class Snippet(models.Model):
        created = models.DateTimeField(auto_now_add=True)  #     
        title = models.CharField(max_length=100, blank=True, default='')  #   
        code = models.TextField()  #   
        linenos = models.BooleanField(default=False)  #       
        language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)  #   
        style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)  #      
    
        class Meta:
            ordering = ('created',)
    
  • データベース移行
  • python manage.py makemigrations snippets
    python manage.py migrate
    

    Serializerクラスの作成
  • snippetsフォルダ内にserializers.pyファイル
  • を作成する.
    from rest_framework import serializers
    from snippets.models import LANGUAGE_CHOICES
    from snippets.models import Snippet
    from snippets.models import STYLE_CHOICES
    
    
    class SnippetSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        title = serializers.CharField(required=False, allow_blank=True, max_length=100)
        code = serializers.CharField(style={'base_template': 'textarea.html'})
        linenos = serializers.BooleanField(required=False)
        language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
        style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
    
        def create(self, validated_data):
            """
            Create and return a new `Snippet` instance, given the validated data.
            """
            return Snippet.objects.create(**validated_data)
    
        def update(self, instance, validated_data):
            """
            Update and return an existing `Snippet` instance, given the validated data.
            """
            instance.title = validated_data.get('title', instance.title)
            instance.code = validated_data.get('code', instance.code)
            instance.linenos = validated_data.get('linenos', instance.linenos)
            instance.language = validated_data.get('language', instance.language)
            instance.style = validated_data.get('style', instance.style)
            instance.save()
            return instance
    

    Serializersクラスの使用
  • Django shell
  • を開く
    python manage.py shell
    
  • Serializersオブジェクトを2つ作成
  • from snippets.models import Snippet
    from snippets.serializers import SnippetSerializer
    from rest_framework.renderers import JSONRenderer
    from rest_framework.parsers import JSONParser
    
    snippet = Snippet(code='foo = "bar"
    ') snippet.save() snippet = Snippet(code='print "hello, world"
    ') snippet.save()

    シーケンス化
  • オブジェクトをシーケンス化する
  • In [11]: serializer = SnippetSerializer(snippet)
    
    In [12]: serializer.data
    Out[12]: 
    ReturnDict([('id', 2),
                ('title', ''),
                ('code', 'print "hello, world"
    '), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
  • dataデータをjson
  • に変換する.
    In [13]: content = JSONRenderer().render(serializer.data)
    
    In [14]: content
    Out[14]: b'{"id":2,"title":"","code":"print \\"hello, world\\"\
    ","linenos":false,"language":"python","style":"friendly"}'

    逆シーケンス化
  • JSONデータをPython生データ型(辞書)
  • に変換
    In [15]: from django.utils.six import BytesIO
    
    In [16]: stream = BytesIO(content)
    
    In [17]: data = JSONParser().parse(stream)
    
    In [18]: data
    Out[18]: 
    {'code': 'print "hello, world"
    ', 'id': 2, 'language': 'python', 'linenos': False, 'style': 'friendly', 'title': ''}
  • Pythonオリジナルデータ型(辞書)をオブジェクト
  • に変換する.
    In [19]: serializer = SnippetSerializer(data=data)
    
    In [20]: serializer.is_valid()
    Out[20]: True
    
    In [21]: serializer.validated_data
    Out[21]: 
    OrderedDict([('title', ''),
                 ('code', 'print "hello, world"'),
                 ('linenos', False),
                 ('language', 'python'),
                 ('style', 'friendly')])
    
    In [22]: serializer.save()
    Out[22]: 
    
  • は、many=Trueパラメータ
  • を追加するだけでクエリーセットをシーケンス化することができる.
    In [23]: serializer = SnippetSerializer(Snippet.objects.all(), many=True)
    
    In [24]: serializer.data
    Out[24]: [OrderedDict([('id', 1), ('title', ''), ('code', 'foo = "bar
    "'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 2), ('title', ''), ('code', 'print "hello, world"
    '), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('id', 3), ('title', ''), ('code', 'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])]

    ModelSerializerの使用
    先ほど定義したSnippetSerializerクラスのクラスの多くは、models.pyで定義した内容と重複していますが、SnippetSerializerクラスをModelSerializerに継承して、このような重複定義を減らすこともできます.
  • は、SnippetSerializerクラスを次のように再定義する:
  • class SnippetSerializer(serializers.ModelSerializer):
        class Meta:
            model = Snippet
            fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
    
  • Django shell
  • を開く
    python manage.py shell
    
  • SnippetSerializerクラス
  • を表示
    In [1]: from snippets.serializers import SnippetSerializer
    
    In [2]: serializer = SnippetSerializer()
    
    In [3]: print(repr(serializer))
    SnippetSerializer():
        id = IntegerField(label='ID', read_only=True)
        title = CharField(allow_blank=True, max_length=100, required=False)
        code = CharField(style={'base_template': 'textarea.html'})
        linenos = BooleanField(required=False)
        language = ChoiceField(choices=[('abap', 'ABAP'), ('abnf', 'ABNF'), ('ada', 'Ada'), ('adl', 'ADL'), ('agda', 'Agda'), ('aheui', 'Aheui'), ('ahk', 'autohotkey'),
     ...
    

    これにより,ModelSerializerクラスに継承され,2つの非常に大きな役割を果たすことが分かった.
  • クラス属性
  • を繰り返し定義する必要はない.
  • 自動所有create()およびupdate()メソッド
  • SerializerのDjango views内での簡単な運用
  • ここではREST frameworkの他の特性は使用されず、従来のDjango views
  • のみが使用される.
  • ここでの書き方には多くの抜け穴があり、チュートリアルのテスト展示としてのみ使用され、本番環境
  • に直接適用することはできません.
    viewsの構成snippets/views.pyを開く
  • 関連パッケージ
  • をインポートする.
    from django.shortcuts import render
    from django.http import HttpResponse, JsonResponse
    from django.views.decorators.csrf import csrf_exempt
    from rest_framework.renderers import JSONRenderer
    from rest_framework.parsers import JSONParser
    from snippets.models import Snippet
    from snippets.serializers import SnippetSerializer
    
  • すべてのオブジェクトとオブジェクトの追加機能を返すAPI
  • を作成する
    @csrf_exempt
    def snippet_list(request):
        """
        List all code snippets, or create a new snippet.
        """
        if request.method == 'GET':
            snippets = Snippet.objects.all()
            serializer = SnippetSerializer(snippets, many=True)
            return JsonResponse(serializer.data, safe=False)
    
        elif request.method == 'POST':
            data = JSONParser().parse(request)
            serializer = SnippetSerializer(data=data)
            if serializer.is_valid():
                serializer.save()
                return JsonResponse(serializer.data, status=201)
            return JsonResponse(serializer.errors, status=400)
    
  • オブジェクトの検索、変更、削除機能を作成するAPI
  • @csrf_exempt
    def snippet_detail(request, pk):
        """
        Retrieve, update or delete a code snippet.
        """
        try:
            snippet = Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            return HttpResponse(status=404)
    
        if request.method == 'GET':
            serializer = SnippetSerializer(snippet)
            return JsonResponse(serializer.data)
    
        elif request.method == 'PUT':
            data = JSONParser().parse(request)
            serializer = SnippetSerializer(snippet, data=data)
            if serializer.is_valid():
                serializer.save()
                return JsonResponse(serializer.data)
            return JsonResponse(serializer.errors, status=400)
    
        elif request.method == 'DELETE':
            snippet.delete()
            return HttpResponse(status=204)
    

    urlsの構成
  • 作成snippets/urls.py
  • from django.conf.urls import url
    from snippets import views
    
    urlpatterns = [
        url(r'^snippets/$', views.snippet_list),
        url(r'^snippets/(?P[0-9]+)/$', views.snippet_detail),
    ]
    
  • 配置項目根urls.py
  • from django.conf.urls import url
    from django.conf.urls import include
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^', include('snippets.urls')),
    ]
    

    テストインタフェース
  • サービス
  • を開始
    (django_rest_framework) [root@localhost tutorial]# python manage.py runserver
    Performing system checks...
    
    System check identified no issues (0 silenced).
    November 20, 2017 - 23:01:29
    Django version 1.11.7, using settings 'tutorial.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CONTROL-C.
    
  • 別のshellウィンドウ
  • を開く
  • は、http要求
  • をシミュレートするためのhttpieパケットをインストールする.
    pip install httpie
    
  • は要求を送信し、すべてのsnippetsオブジェクト
  • を取得する.
    (django_rest_framework) [root@localhost tutorial]# http http://127.0.0.1:8000/snippets/
    HTTP/1.0 200 OK
    Content-Length: 352
    Content-Type: application/json
    Date: Mon, 20 Nov 2017 15:03:10 GMT
    Server: WSGIServer/0.2 CPython/3.6.3
    X-Frame-Options: SAMEORIGIN
    
    [
        {
            "code": "foo = \"bar
    \"", "id": 1, "language": "python", "linenos": false, "style": "friendly", "title": "" }, { "code": "print \"hello, world\"
    ", "id": 2, "language": "python", "linenos": false, "style": "friendly", "title": "" }, ]
  • は要求を送信し、プライマリキーが2のsnippetsオブジェクト
  • を取得する.
    (django_rest_framework) [root@localhost tutorial]# http http://127.0.0.1:8000/snippets/2/
    HTTP/1.0 200 OK
    Content-Length: 119
    Content-Type: application/json
    Date: Mon, 20 Nov 2017 15:03:17 GMT
    Server: WSGIServer/0.2 CPython/3.6.3
    X-Frame-Options: SAMEORIGIN
    
    {
        "code": "print \"hello, world\"
    ", "id": 2, "language": "python", "linenos": false, "style": "friendly", "title": "" }

    について
    私は初めてDjango REST frameworkを学んで、Django REST framework学習紀要シリーズの文章は私が公式サイトのドキュメントから学習した後の初歩的な消化の成果で、もし間違いがあれば、指摘を歓迎します.
    学習用コードGithubウェアハウス:shelmingsong/django_rest_framework
    参考になる公式サイトのドキュメント:Tutorial 1:Serialization
    ブログ更新アドレス
  • 宋明耀のブログ[第1時間更新]
  • コラムPython Cookbook
  • 流月0の文章