drf--part2
- 一、區域鉤子和全域鉤子
- 1、區域鉤子
- 2、全域鉤子
- 3、常用欄位和引數
- 二、視圖相關
- 1、保存資料
- 2、更新資料
- 三、modelSerializer的使用
- 四、回應狀態碼
一、區域鉤子和全域鉤子
接上篇:
1、區域鉤子
在反序列化校驗中,我們不僅可以通過validators來自定義校驗函式,也可以使用鉤子函式來進行校驗,首先我們介紹區域鉤子,
區域鉤子用在單個屬性的校驗,具體寫法如下:
from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
name = serializers.CharField(max_length=4)
age = serializers.IntegerField(max_value=80)
class_null = serializers.CharField()
description = serializers.CharField(allow_blank=True)
# 區域鉤子如下:
def validate_name(self,val): #函式定義規則為:validate_(要校驗屬性)
if '777' in val:
raise serializers.ValidationError('資料校驗未通過')
return val
接下來我們使用postman給介面發送post請求,并得到ok回傳值:

我們接下來來看服務端回應結果:

如圖,區域鉤子生效,
2、全域鉤子
全域鉤子主要針對多個屬性進行校驗,寫法如下:
from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
name = serializers.CharField(max_length=4)
age = serializers.IntegerField(max_value=80)
class_null = serializers.CharField()
description = serializers.CharField(allow_blank=True)
# 全域鉤子如下:
def validate(self,data): # data為post請求發送過來的有序字典資料
# 我們可以列印下data
print(data)
name = data.get('name')
description = data.get('description')
if name == description:
raise serializers.ValidationError('名字和簡介不能相等')
return data
我們繼續使用postman向介面發送post請求:

我們接下來來看服務端回應結果:

如圖,全域鉤子生效,
執行順序:
1、執行is_valid()方法時,先校驗序列化器中的所有屬性field對應的規則
2、執行區域鉤子
3、最后執行全域鉤子
3、常用欄位和引數
常用欄位型別:
| 欄位 | 欄位構造方式 |
|---|---|
| BooleanField | BooleanField() |
| NullBooleanField | NullBooleanField() |
| CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
| EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
| RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
| SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正則欄位,驗證正則模式 [a-zA-Z0-9-]+ |
| URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
| UUIDField | UUIDField(format=‘hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 微軟時間戳,通過微秒生成一個隨機字串 |
| IPAddressField | IPAddressField(protocol=‘both’, unpack_ipv4=False, **options) |
| IntegerField | IntegerField(max_value=None, min_value=None) |
| FloatField | FloatField(max_value=None, min_value=None) |
| DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位數 decimal_palces: 小數點位置 |
| DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
| DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
| TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
| DurationField | DurationField() |
| ChoiceField | ChoiceField(choices) choices與Django的用法相同 |
| MultipleChoiceField | MultipleChoiceField(choices) |
| FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| ListField | ListField(child=, min_length=None, max_length=None) |
| DictField | DictField(child=) |
選項引數:
| 引數名稱 | 作用 |
|---|---|
| max_length | 最大長度 |
| min_length | 最小長度 |
| allow_blank | 是否允許為空 |
| trim_whitespace | 是否截斷空白字符 |
| max_value | 最大值 |
| min_value | 最小值 |
通用引數:
| 引數名稱 | 說明 |
|---|---|
| read_only | 表明該欄位僅用于序列化輸出,默認False |
| write_only | 表明該欄位僅用于反序列化輸入,默認False |
| required | 表明該欄位在反序列化時必須輸入,默認True |
| default | 反序列化時使用的默認值 |
| allow_null | 表明該欄位是否允許傳入None,默認False |
| validators | 該欄位使用的驗證器 |
| error_messages | 包含錯誤編號與錯誤資訊的字典 |
| label | 用于HTML展示API頁面時,顯示的欄位名稱 |
| help_text | 用于HTML展示API頁面時,顯示的欄位幫助提示資訊 |
二、視圖相關
我們需要通過視圖函式來進行資料庫的操作
1、保存資料
方法一:
將校驗通過的資料提交至資料庫,我們可以通過is_valid()來進行判斷,再用orm將資料寫入資料庫:
from django.shortcuts import render,HttpResponse
from student01.models import Student
from .serializers import StudentSerializer
from django.http import JsonResponse
from django.views import View
# Create your views here.
class StudentView(View):
def post(self,request):
data=request.POST
ser = StudentSerializer(data=data)
print(ser.is_valid())
#校驗判斷,校驗成功將資料寫入資料庫,校驗失敗回傳給錯誤提示
if ser.is_valid():
obj=Student.objects.create(
**ser.validated_data
)
serializer=StudentSerializer(instance=obj)
return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False})
else:
return JsonResponse({'error':'有欄位錯誤'})
使用postman來進行測驗:
我們還是使用之前的校驗規則,先發送一個非法資料:

可以看到,成功回傳了錯誤資訊,
接下來我們發送一條合法資料:

接下來我們在資料庫中驗證資料是否被成功寫入:

如圖,成功寫入資料,
方式二:
在序列器中定義create方法來保存資料:
serializers.py:
from rest_framework import serializers
from student01 import models
class StudentSerializer(serializers.Serializer):
name = serializers.CharField(max_length=4)
age = serializers.IntegerField(max_value=80)
class_null = serializers.CharField()
description = serializers.CharField(allow_blank=True)
# 全域鉤子如下:
def validate(self,data): # data為post請求發送過來的有序字典資料
# 我們可以列印下data
print(data)
name = data.get('name')
description = data.get('description')
if name == description:
raise serializers.ValidationError('名字和簡介不能相等')
return data
# 定義create方法
def create(self, validated_data):
obj=models.Student.objects.create(
**validated_data
)
return obj
views.py:
from django.shortcuts import render,HttpResponse
from student01.models import Student
from .serializers import StudentSerializer
from django.http import JsonResponse
from django.views import View
# Create your views here.
class StudentView(View):
def post(self,request):
data=request.POST
ser = StudentSerializer(data=data)
print(ser.is_valid())
#校驗判斷,校驗成功將資料寫入資料庫,校驗失敗回傳給錯誤提示
if ser.is_valid():
# =通過save觸發序列化器中的create方法
instance = ser.save()
serializer=StudentSerializer(instance=instance)
return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False})
else:
return JsonResponse({'error':'有欄位錯誤'})
我們用postman來進行測驗:

成功拿到回傳的資料,接下來我們去資料庫驗證:

資料成功寫入!
2、更新資料
更新資料視圖檔案中需使用put方法,必須寫instance,序列化器中需定義update方法,具體寫法如下:
serializers.py:
from rest_framework import serializers
from student01 import models
class StudentSerializer(serializers.Serializer):
name = serializers.CharField(max_length=4)
age = serializers.IntegerField(max_value=80)
class_null = serializers.CharField()
description = serializers.CharField(allow_blank=True)
# 全域鉤子如下:
def validate(self,data): # data為post請求發送過來的有序字典資料
# 我們可以列印下data
print(data)
name = data.get('name')
description = data.get('description')
if name == description:
raise serializers.ValidationError('名字和簡介不能相等')
return data
# 定義create方法
def create(self, validated_data):
obj=models.Student.objects.create(
**validated_data
)
return obj
# 更新資料,定義update方法
def update(self, instance, validated_data):
print(validated_data['name'])
instance.name=validated_data['name']
instance.age=validated_data['age']
instance.class_null=validated_data['class_null']
instance.description=validated_data['description']
instance.save()
return instance
views.py:
from django.shortcuts import render,HttpResponse
from student01.models import Student
from .serializers import StudentSerializer
from django.http import JsonResponse
from django.views import View
from django.http.request import QueryDict
# Create your views here.
class StudentView(View):
def post(self,request):
data=request.POST
ser = StudentSerializer(data=data)
print(ser.is_valid())
#校驗判斷,校驗成功將資料寫入資料庫,校驗失敗回傳給錯誤提示
if ser.is_valid():
# =通過save觸發序列化器中的create方法
instance = ser.save()
serializer=StudentSerializer(instance=instance)
return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False})
else:
return JsonResponse({'error':'有欄位錯誤'})
def put(self,request):
ret=QueryDict(request.body)
data={
'id':ret.get('id'),
'name':ret.get('name'),
'age':ret.get('age'),
'class_null':ret.get('class_null'),
'description':ret.get('description')
}
ret1=Student.objects.get(id=data.get('id'))
ret2=StudentSerializer(instance=ret1,data=data)
if ret2.is_valid():
ret2.save()
return HttpResponse('ok')
else:
return JsonResponse({'error':'有欄位錯誤'})
postman傳入一組資料測驗:

資料庫中查看更新結果:

三、modelSerializer的使用
read-only:序列化時序列化出該欄位資料,反序列化時不校驗這個資料
write-only:序列化時不序列化這個欄位資料,反序列化時需客戶端傳遞這個資料進行校驗
partial:只需要校驗傳入給序列化器的資料,適用于部分資料更新
序列化器serializers.py:
from rest_framework import serializers
from student01 import models
class StudentModelSerializer(serializers.ModelSerializer):
class Meta:
model=models.Student
fields='__all__'
extra_kwargs={
'id':{'read_only':True},
'age':{'write_only':True}
}
views.py:
from django.shortcuts import render
from django.http import JsonResponse
# Create your views here.
from django.views import View
from .serializers import StudentModelSerializer
from student01 import models
class StudentView(View):
def get(self,request):
all = models.Student.objects.all()
serializers=StudentModelSerializer(instance=all,many=True)
return JsonResponse(serializers.data,safe=False,json_dumps_params={'ensure_ascii':False})
def post(self,request):
data=request.POST
serializers=StudentModelSerializer(data=data)
if serializers.is_valid():
serializers.save() #能夠自動幫我們保存資料,不用在序列化器中創建create方法
return JsonResponse({'info':'資料保存成功!'})
else:
return JsonResponse({'error':'非法資料!'})
我們使用postman進行測驗:

我們在資料庫查看執行結果:

如圖,資料成功寫入
四、回應狀態碼
寫法:
from rest_framework import status
# return Response({'xx':'xxxxx'}, status=201)
return Response({'xx':'xxxxx'}, status=status.HTTP_201_CREATED)
所有狀態碼:
HTTP_100_CONTINUE = 100
HTTP_101_SWITCHING_PROTOCOLS = 101
HTTP_200_OK = 200
HTTP_201_CREATED = 201
HTTP_202_ACCEPTED = 202
HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
HTTP_204_NO_CONTENT = 204
HTTP_205_RESET_CONTENT = 205
HTTP_206_PARTIAL_CONTENT = 206
HTTP_207_MULTI_STATUS = 207
HTTP_208_ALREADY_REPORTED = 208
HTTP_226_IM_USED = 226
HTTP_300_MULTIPLE_CHOICES = 300
HTTP_301_MOVED_PERMANENTLY = 301
HTTP_302_FOUND = 302
HTTP_303_SEE_OTHER = 303
HTTP_304_NOT_MODIFIED = 304
HTTP_305_USE_PROXY = 305
HTTP_306_RESERVED = 306
HTTP_307_TEMPORARY_REDIRECT = 307
HTTP_308_PERMANENT_REDIRECT = 308
HTTP_400_BAD_REQUEST = 400
HTTP_401_UNAUTHORIZED = 401
HTTP_402_PAYMENT_REQUIRED = 402
HTTP_403_FORBIDDEN = 403
HTTP_404_NOT_FOUND = 404
HTTP_405_METHOD_NOT_ALLOWED = 405
HTTP_406_NOT_ACCEPTABLE = 406
HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
HTTP_408_REQUEST_TIMEOUT = 408
HTTP_409_CONFLICT = 409
HTTP_410_GONE = 410
HTTP_411_LENGTH_REQUIRED = 411
HTTP_412_PRECONDITION_FAILED = 412
HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
HTTP_414_REQUEST_URI_TOO_LONG = 414
HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
HTTP_417_EXPECTATION_FAILED = 417
HTTP_418_IM_A_TEAPOT = 418
HTTP_422_UNPROCESSABLE_ENTITY = 422
HTTP_423_LOCKED = 423
HTTP_424_FAILED_DEPENDENCY = 424
HTTP_426_UPGRADE_REQUIRED = 426
HTTP_428_PRECONDITION_REQUIRED = 428
HTTP_429_TOO_MANY_REQUESTS = 429
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
HTTP_500_INTERNAL_SERVER_ERROR = 500
HTTP_501_NOT_IMPLEMENTED = 501
HTTP_502_BAD_GATEWAY = 502
HTTP_503_SERVICE_UNAVAILABLE = 503
HTTP_504_GATEWAY_TIMEOUT = 504
HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
HTTP_506_VARIANT_ALSO_NEGOTIATES = 506
HTTP_507_INSUFFICIENT_STORAGE = 507
HTTP_508_LOOP_DETECTED = 508
HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509
HTTP_510_NOT_EXTENDED = 510
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/191890.html
標籤:其他
