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即可.