zoukankan      html  css  js  c++  java
  • Django REST framework -- Serialization

    Django REST framework

    Django 支持MTV模式, 前端渲染的内容,放在了后端 template中实施,包括获取数据,渲染模板一系列过程都在候选执行。

    在前端能力强大的现在, 前后端分离开发模式已经成为主流, 所以后端只提供API, 于前端进行数据交互,成为业界主流。

    此框架,就是在Django框架基础之上, 做了一层上层封装, 专门为后端API设计。

    https://www.django-rest-framework.org/

    Django REST framework is a powerful and flexible toolkit for building Web APIs.

    Some reasons you might want to use REST framework:

    Mini Demo Code

    在django定义的 url 和 model基础之上

    restframework 提供了  路由 序列化 视图集模块, 非常容易实现一个简单的应用。

    https://www.django-rest-framework.org/

    from django.urls import path, include
    from django.contrib.auth.models import User
    from rest_framework import routers, serializers, viewsets
    
    # Serializers define the API representation.
    class UserSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = User
            fields = ['url', 'username', 'email', 'is_staff']
    
    # ViewSets define the view behavior.
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    # Routers provide an easy way of automatically determining the URL conf.
    router = routers.DefaultRouter()
    router.register(r'users', UserViewSet)
    
    # Wire up our API using automatic URL routing.
    # Additionally, we include login URLs for the browsable API.
    urlpatterns = [
        path('', include(router.urls)),
        path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
    ]

     

    Tutorial

    Serialization

    https://www.django-rest-framework.org/tutorial/1-serialization/#using-modelserializers

    序列化工具中有个序列化类, 继承此类的类, 面向具体的model,定义序列化参数。

    其功能是, 将 字符串的 数据格式, 转换为 plain 类型的python词典对象, 然后将此词典对象, 转换为ORM对象(django model), 再由ORM对象做持久化操作。

    这是正向转换, 是client传送字符串格式数据到数据库中, 反向操作, 是将数据库中的数据转换为 字符串格式数据, 用于向客户端反馈。

    The first thing we need to get started on our Web API is to provide a way of serializing and deserializing the snippet instances into representations such as json. We can do this by declaring serializers that work very similar to Django's forms. Create a file in the snippets directory named serializers.py and add the following.

    模型定义

    from django.db import models
    from pygments.lexers import get_all_lexers
    from pygments.styles import get_all_styles
    
    LEXERS = [item for item in get_all_lexers() if item[1]]
    LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
    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']

    模型对应的序列化类, 可以发现,其中数据field的定义存在重复。

    from rest_framework import serializers
    from snippets.models import Snippet, LANGUAGE_CHOICES, 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

    模型的实例化, 并保存数据。

    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()

    序列化类, 将模型转化为 普通的 python词典对象。

    serializer = SnippetSerializer(snippet)
    serializer.data
    # {'id': 2, 'title': '', 'code': 'print("hello, world")
    ', 'linenos': False, 'language': 'python', 'style': 'friendly'}

    使用工具, 将python词典对象, 转换为 字符串格式数据。

    content = JSONRenderer().render(serializer.data)
    content
    # b'{"id": 2, "title": "", "code": "print(\"hello, world\")\n", "linenos": false, "language": "python", "style": "friendly"}'

    反向操作, 将字符串数据,转换为普通的python 词典对象。

    import io
    
    stream = io.BytesIO(content)
    data = JSONParser().parse(stream)

    将词典对象, 传入序列化类, 做数据field合法性检查, 并保存到数据库。

    serializer = SnippetSerializer(data=data)
    serializer.is_valid()
    # True
    serializer.validated_data
    # OrderedDict([('title', ''), ('code', 'print("hello, world")
    '), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
    serializer.save()
    # <Snippet: Snippet object>

    使用 ModelSerializer 可以复用 model的数据field, 避免数据field重复定义。

    class SnippetSerializer(serializers.ModelSerializer):
        class Meta:
            model = Snippet
            fields = ['id', 'title', 'code', 'linenos', 'language', 'style']

    使用django view, 将正向和反向数据序列化串起来。

    获取所有数据, 创建单个数据。

    @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)

    获取和修改和删除单个数据。

    @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)

    django function view注册到URLconf

    from django.urls import path
    from snippets import views
    
    urlpatterns = [
        path('snippets/', views.snippet_list),
        path('snippets/<int:pk>/', views.snippet_detail),
    ]
    出处:http://www.cnblogs.com/lightsong/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
  • 相关阅读:
    laydate 时间框弹窗点击弹出后立马消失的问题解决
    万字长文:ELK(V7)部署与架构分析
    人声消除的原理算法源码及方案实现
    主动降噪技术(ANC)的前生今世–行业分析
    主动降噪技术(ANC)的前生今世--原理仿真
    主动降噪技术(ANC)的前生今世--概念历史
    音频人生
    解决 Flask-sqlalchemy 中文乱码
    使用 key 登录时分开记录操作历史记录
    OpenSSH 使用技巧
  • 原文地址:https://www.cnblogs.com/lightsong/p/15397975.html
Copyright © 2011-2022 走看看