django——rest framework Serializer

Serializer

  在這裏通過一個驗證用戶身份的例子說明rest_framework中serializer.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_authenticated或is_superuser等判斷auth信息是否符合要求.auth的用戶名和密碼可以通過request.user.username和request.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即可.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章