zoukankan      html  css  js  c++  java
  • Django的Serializers的使用

    Serializer

      在这里通过一个验证用户身份的例子说明rest_frameworkserializer.Serialize的使用.

      编写serializer

      Serializer的使用不需要依赖于模型,所以可以不要编写model,直接编写serializer文件.

    from rest_framework import serializers
    
    
    class TestSerializer(serializers.Serializer):
    
        name = serializers.CharField(max_length=20, required=True)
        code = serializers.CharField(max_length=20, required=True)

      编写View

      使用rest_framework的APIView编写视图,实现get和post方法

    from django.http import HttpResponse, JsonResponse
    from django.contrib.auth import authenticate
    from rest_framework import status
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from school.serializers.school import TestSerializer
    
    
    class TestView(APIView):
    
        def get(self, request):
            # 获取auth中的用户
            user = request.user
            if user.is_authenticated:   # is_superuser
                return HttpResponse(user.username + '已授权')
            return HttpResponse('未授权')
    
        def post(self, request):
            serializer = TestSerializer(data=request.data)
    
            if serializer.is_valid():
                username = serializer.validated_data.get("name", "")
                password = serializer.validated_data.get("code", "")
    
                # 调用authenticate方法
                user = authenticate(username=username, password=password)
    
                if user is not None:
                    content = {
                        "status": True,
                        "message": "账户正确"
                    }
                    return JsonResponse(data=content, status=status.HTTP_200_OK)
                else:
                    content = {
                        "status": False,
                        "message": "账号或者密码不正确"
                    }
                    return JsonResponse(data=content, status=status.HTTP_200_OK)
            else:
                return Response(data=serializer.errors)

      使用django的view和rest_framework的APIView实现get和post方法时,无论是否显示使用到request,都需要request参数,否则会出错

     get:  

        首先通过request.user获取auth信息

        然后根据is_authenticatedis_superuser等判断auth信息是否符合要求.auth的用户名和密码可以通过request.user.usernamerequest.user.password获取

     post:

      在前面的get方法中并未使用到serializer,只是获取了auth信息.而且post方法中将serializer结合post参数验证user信息.

        首先,通过post的参数创建一个序列化类实例

        然后,判断序列化实例是否有效,无效则直接返回序列化错误信息

        当序列化有效时,通过serializer.validaated_data.get()获取post数据参数.注意,只能获取到serializer类中定义的字段值.在该例子中,name和code在TestSerializer中有定义,当post参数名为那么和code时可以获取,否则不能获取.比如,当post有个参数是username时,使用serializer.validated_data.get("username","")不能得到username的参数值.

    ModelSerializer

      ModelSerializer的使用需要依赖于已有model模型,常用来编写api.这里只介绍ModelSerializer的使用,view方面不作说明.

     创建模型:

        首先需要创建模型,这里拿一个外键关联的例子来说明

    from django.db import models
    
    
    class School(models.Model):
        name = models.CharField(max_length=32, verbose_name="名称")
        code = models.CharField(max_length=16, verbose_name="代码")
        location = models.CharField(max_length=128, verbose_name="地址")
    
    
    class Student(models.Model):
        name = models.CharField(max_length=32, verbose_name="姓名")
        age = models.IntegerField(verbose_name="年龄")
        school = models.ForeignKey(to=School,verbose_name="学校", on_delete=models.CASCADE)

      这里,有两个模型,Student模型通过school字段关联School模型,on_delete=models.CASCADE表示删除School实例时会级联删除Student实例.

     序列化

        由于School只有三个基本类型字段,所以这里以Student的序列化为例进行说明.

    # -*- coding: utf-8 -*-
    from rest_framework import serializers
    
    from school.models import Student, School
    
    
    class StudentSerializer(serializers.ModelSerializer):
        # 多对多时添加参数 many=True
        school = serializers.SlugRelatedField(read_only=False, slug_field="name", queryset=School.objects.all())
        # address = serializers.CharField(source="school.address", default=None)
    
        def create(self, validated_data):
            # some actions
            instance = super().create(validated_data)
            return instance
    
        def update(self, instance, validated_data):
            user = self.context['request'].user        # 请求的用户
            username = self.context['request'].data.get('username')     # 请求的参数username
            instance.name = validated_data['name']      # 请求的参数name
            # some actions
            instance.save()
            return instance
    
        class Meta:
            model = Student
            fields = ('id', 'name', 'age', 'school')
            read_only_fields = ('id', 'age')

      在这里值得注意的地方主要有三点:序列化外键字段丶重写create方法丶重写update方法.

      在序列化外键字段时,如果要使用被关联对象的某个字段来代表该字段,可以使用SlugRelatedField.在多对多情况下还需要添加参数many = True,当然,也可以另起一个字段来展示被关联对象某个字段的值,如:

    address = serializers.CharField(source="school.address", default=None)

      除了上面的方法,还可以使用一个更通用的方法,可以序列化非模型中的字段或者外键的外键等.

      使用SerializerMethodField通过定义方法序列化:

    status = serializers.SerializerMethodField()
    
    def get_status_verbose(self, obj):
        # obj表示当前模型对象
        return obj.get_status_display()

      重写create方法有两个参数,validated_data中是创建实例各字段的值,调用super().create(validated_data)即创建了实例,返回实例对象instance.我们可以在调用父类的create方法前后做一些处理,比如在调用之前对validated_data中的字段重新赋值.当创建成功时,如果需要附带自动创建日志实例时,可以将instance作为日志实例的外键创建日志实例.最后将创建的Student实例instance返回出去.

      重写update方法有三个参数,instance是要修改的模型实例,validated_data是请求的参数.在update方法中,我们一般需要获取相关数据来修改模型的值,主要可以归为三种,第一,获取用户信息,使用self.context['request'].user.  第二,请求参数中的数据,但是参数的名称与模型字段的名称不一致,无法通过validated_data获取,使用self.context['request'].data.get('username')获取.第三,请求参数中与模型字段名一致的数据,直接使用validated_data['name]获取.获取完数据后可以对instance的字段进行一些赋值操作,最后保存instance即可.

  • 相关阅读:
    Swift如何判断上午还是下午
    Qt Creator编译app到iPhone
    用swift判断string是否包含字母
    QToolTip显示富文本问题
    mac如何发起屏幕共享?
    Redis持久化
    bean 实例化原理解析
    WebSocket和SocketIO总结
    netty入门
    redis 工具类
  • 原文地址:https://www.cnblogs.com/qicun/p/10079490.html
Copyright © 2011-2022 走看看