人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

Django序列化組件Serializers使用詳解

發(fā)布日期:2022-01-02 19:46 | 文章來源:腳本之家

本文主要系統(tǒng)性的講解django rest framwork 序列化組件的使用,基本看完可以解決工作中序列化90%的問題,寫作參考官方文檔https://www.django-rest-framework.org/api-guide/serializers/#modelserializer,分成如下九個部分:

01、為什么要用序列化組件

我們知道前后端常用json數(shù)據(jù)結構交互, 在后端我們常想把一個對象返回給前端,但是json序列化是不能序列化對象(不過可以添加序列化參數(shù)encoder序列化原理和序列化組件差不多需要自己定義序列化類和返回的結構),所以就有了我們的序列化組件,可以自定義特定結構把對象序列化返回給前端,同時可以對前端傳入的參數(shù)進行數(shù)據(jù)校驗等功能。

02、序列化組件的基本使用

models

from django.db import models
# Create your models here.

class Book(models.Model):
 id = models.IntegerField(primary_key=True)
 title = models.CharField(max_length=255)
 desc = models.CharField(max_length=255)
 is_deleted = models.IntegerField(choices=[(1, "刪除"), (0, "未刪除")])
 author = models.CharField(max_length=255)

serializer

from rest_framework.serializers import Serializer
from rest_framework import serializers

class BookSerializer(Serializer):
 id = serializers.IntegerField()
 title = serializers.CharField()
 desc = serializers.CharField()
 is_deleted = serializers.ChoiceField(choices=[(1, "刪除"), (0, "未刪除")], source="get_is_deleted_display")
 author = serializers.CharField()

views

from app01.models import Book
from app01.serializer import BookSerializer
from django.http import HttpResponse, JsonResponse
# Create your views here.

def get_books(request):
 books = Book.objects.all()
 se = BookSerializer(books, many=True)
 return JsonResponse(se.data, safe=False)

結果返回:

[{"id": 1, "title": "活著", "desc": "講述一代人的人生", "is_deleted": "未刪除", "author": "余華"}]

在寫法上model和serializer的寫法非常相近,但內(nèi)在邏輯model是與數(shù)據(jù)庫表的關系映射,serializer是對對象的序列化和反序列化。

03、序列化組件常用字段

常用字段類型

字段 字段構造方式
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: 最多位數(shù)
decimal_palces: 小數(shù)點位置
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=)

選項參數(shù):

名稱 作用
max_length 最大長度
min_lenght 最小長度
allow_blank 是否允許為空
trim_whitespace 是否截斷空白字符
max_value 最大值
min_value 最小值

通用參數(shù)

參數(shù)名稱 說明
read_only 表明該字段僅用于序列化輸出,默認False
write_only 表明該字段僅用于反序列化輸入,默認False
required 表明該字段在反序列化時必須輸入,默認True
default 反序列化時使用的默認值
allow_null 表明該字段是否允許傳入None,默認False
validators 該字段使用的驗證器
error_messages 包含錯誤編號與錯誤信息的字典
label 用于HTML展示API頁面時,顯示的字段名稱
help_text 用于HTML展示API頁面時,顯示的字段幫助提示信息

在這里額外講一個參數(shù)source,在官方文檔中是這樣解釋的:

將用于填充字段的屬性的名稱??梢允莾H接受self參數(shù)的方法,例如URLField(source='get_absolute_url'),也可以使用點分符號遍歷屬性,例如EmailField(source='user.email')。當使用點分符號序列化字段時,default如果在屬性遍歷期間任何對象不存在或為空,則可能需要提供一個值。

該值source='*'具有特殊含義,用于指示應將整個對象傳遞給該字段。這對于創(chuàng)建嵌套表示或?qū)π枰L問完整對象才能確定輸出表示的字段很有用。

默認為字段名稱。

其中比較常用的用法:

1、source="get_field_name_display"如上所展示,在choice字段中可以展示選項對應的解釋,這中用法代表的是官方解釋說的可以是僅接受self參數(shù)的方法,也就是source中可以填serializer對象可以調(diào)用的方法(方法中需要傳入self),內(nèi)在邏輯是這個字段會展示此方法的返回的結果。

2、source='user.email'這種用法常在ModelSerializer的子類中,其中user為User對象,此中寫法是指展示user的email屬性,常用于我們想把外鍵對象user的屬性和本對象的屬性展示在同一層級,而不是下一級。

04、序列化組件is_valid、validated_data

當我們定義好序列化器時,怎么校驗傳入的字段呢?那就是is_valid方法,可以根據(jù)定義序列化器的校驗規(guī)則判斷傳入字段是否合法。

serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']}

然后serializer.validated_data就可以獲取校驗過后的數(shù)據(jù)字典。

05、序列化組件校驗字段

序列化組件校驗字段的方式常有三種:

1、首先是在字段的validators屬性, 其中傳入一個校驗方法列表如:validators=(my_validator, )其中my_validator中定義校驗規(guī)則。

def multiple_of_ten(value):
 if value % 10 != 0:
  raise serializers.ValidationError('Not a multiple of ten')
class GameRecord(serializers.Serializer):
 score = IntegerField(validators=[multiple_of_ten])

2、最常用的是定義一個validate_field_name(self, value)的函數(shù)(其中field_name指的是字段名),函數(shù)內(nèi)是具體的邏輯。

from rest_framework import serializers
class BlogPostSerializer(serializers.Serializer):
 title = serializers.CharField(max_length=100)
 content = serializers.CharField()
 def validate_title(self, value):
  """
  Check that the blog post is about Django.
  """
  if 'django' not in value.lower():
raise serializers.ValidationError("Blog post is not about Django")
  return value

3、最后一種是定義一個validate(self, data)其中data是所有字段的鍵值對,所以這個校驗方法是對象級別的校驗。

from rest_framework import serializers
class EventSerializer(serializers.Serializer):
 description = serializers.CharField(max_length=100)
 start = serializers.DateTimeField()
 finish = serializers.DateTimeField()
 def validate(self, data):
  """
  Check that start is before finish.
  """
  if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
  return data

當然或許當你看到這里會問why?how? 只能說源碼是最好的答案。

06、序列化組件.create() and .update()

在我們定義的序列化類中, 可以添加create和update方法,當我們有需求是根據(jù)反序列化后的數(shù)據(jù)在數(shù)據(jù)庫表中創(chuàng)建記錄或者更新某條數(shù)據(jù),這時我們就可以在create方法和update方法中定義對應的邏輯。

class CommentSerializer(serializers.Serializer):
 email = serializers.EmailField()
 content = serializers.CharField(max_length=200)
 created = serializers.DateTimeField()
   def create(self, validated_data):
  return Comment.objects.create(**validated_data)
 def update(self, instance, validated_data):
  instance.email = validated_data.get('email', instance.email)
  instance.content = validated_data.get('content', instance.content)
  instance.created = validated_data.get('created', instance.created)
  instance.save()
  return instance

接下來調(diào)用serializer.save()命令便可創(chuàng)建一條紀錄或者更新一條記錄,其中判斷save時什么時候是創(chuàng)建什么時候是更新呢?關鍵在于serializer的實例化。

# .save() will create a new instance.
serializer = CommentSerializer(data=data)
serializer.save()
# .save() will update the existing `comment` instance.
 serializer = CommentSerializer(comment, data=data)
serializer.save()

其中當Serializer類實例化沒有傳入model對象時會調(diào)用create方法創(chuàng)建一條記錄, 如果Serializer類實例化時傳入了model對象就會調(diào)用update方法更新一條記錄。

有時除了反序列化的字段我們還需要其他字段怎么辦呢?我們可以在save中傳入?yún)?shù)名和值,可以在validated_data中根據(jù)參數(shù)名取到對應的值。

serializer.save(owner=request.user)

這樣我們就可以在validated_data.get("owner")就可以取到user對象了。

07、序列化組件ModelSerializer

ModelSerializer和表單的ModelForm組件很相似,都極大簡化了我們的開發(fā),可以在內(nèi)部類Meta中定義對應的model,ModelSerializer就會自動生成model字段對應的Field不用我們定義。

class AccountSerializer(serializers.ModelSerializer):
 class Meta:
  model = Account
  fields = ['id', 'account_name', 'users', 'created']

 其中fields中定義序列化的字段,如果是全部字段就寫__all__, 上述例子我們沒有定義具體的字段,ModelSerializer幫我們自動生成了 'id', 'account_name', 'users', 'created'的Field。

08、序列化組件構造復雜的結構

以下是個存在一對多和多對多字段的序列化器

serializer

from res_framework import serializers
#這個類用于被實例化,多對多字段這么寫
class AuthorSerializer(serializers.Serializer):
 id = serializers.Charfield()
 name = serializers.Charfield()
 age = serializers.Charfield()
#傳給views.py的主類
class BookSerializer(serializers.Serializer):
 name = serializers.Charfield()
 #source 可以指定字段 ,  id是要序列化的表名。
 id  = serializers.CharField(source='nid') 
 #,source后字段用.的方式可以跨表查詢。
 publish = serializer.CharField(source='publish.email')
 ''' 
 如果在models.py的book類中定義一個test方法。
 def test(self): 
  return str(self.price)+self.name
'''
# 返回的結果就會有xx字段,souce不但可以指定表模型字段,還可以指定模型表方法,并且賦值給xx變量
xx = serializers.Charfield(source='test')


#外鍵的實現(xiàn)方法:
#一對多字段
#如果要通過外鍵字段返回出版社的所有信息,包括id,name,email...
#obj是當前循環(huán)序列化到的數(shù)據(jù)對象
 publish = serializers.SerializerMethodField()
 def get_publish(self,obj):
  return {'id‘:obj.publish.pk,'name':obj.publish.name}

#多對多字段
#所有作者的詳情,也展示出來
 authors = serializers.SerializermethodFiled()
 def get_authors(self,obj):
  author_list  = obj.authors.all()
  author_ser = AuthorSerializer(author_list,many=True)
  return author_ser.data

views

from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import models
class BookView(APIview):
 def get(self,request,*args,**kwargs):
#獲取所有圖書數(shù)據(jù)
  response = {'status':100,'msg':'獲取成功'}
  book_list = models.Book.objects.all()
  #實例化BookSerializer類,把要序列化的數(shù)據(jù)book_list傳入
  #如果要序列化querySet對象,一定要加many = True
  book_ser = BookSerializer(book_list,many=True)
  #把序列化后的數(shù)據(jù)book_ser.data 拿出來放到response字典中返回給客戶端
  response['data'] = book_ser.data 
  return Response(response)

如果使用ModelSerializer:

serializer

from app01 import models
class PublishSerializer(serializers.ModelSerializer): 
 class Meta: #固定寫法
 # 指定要序列化Book表
 model = models.Book
 #指定要序列化的字段
 fields = ['nid','name']
 #序列化所有字段
 fileds ='__all__‘ 
 #要排除的字段(不能與fileds連用)
 # exclude = ['name','price'] 
 #深度判定
 depth = 1 
 #如果要不按照父類的來,想要自己定義顯示的字段的話,自己定義一個,覆蓋掉父類的字段屬性。
 publish = serializers.SerializerMethodField()  #一對多字段
 def get_publish(self,obj):
  return {'id‘:obj.publish.pk,'name':obj.publish.name}

這里額外解釋一下depth這個參數(shù):在對象外鍵另一對象,另一對象又外鍵另一對象以此類推,depth的作用就是可以決定序列化時的外鍵深度。

復雜序列化器的要點在于,serializers.SerializerMethodField()和get_field_name的使用獲取自己想得到的字段值,還有source的使用,上面有講。

09、序列化組件修改返回值to_representation、to_internal_value

to_representation(self, instance):如果序列化器定義了此方法,可以改變序列化對象data的值,也就是serializer.data的值,你可以根據(jù)自己的業(yè)務場景去重新構造返回值。

def to_representation(self, instance):
 """Convert `username` to lowercase."""
 ret = super().to_representation(instance)
 ret['username'] = ret['username'].lower()
 return ret

to_internal_value(self, data): data為未經(jīng)校驗的數(shù)據(jù)字段, 此方法可以實現(xiàn)校驗和修改反序列化后的值,然后返回。如果不想修改反序列化后的值只是做校驗的話,完全可以使用validate方法替代。

def to_internal_value(self, value):
 if value == None:
  return 0
 return value

總而言之,這兩個方法一個是用于重新構造validated_data并返回,一個用于重新構造serializer.data的值并返回。

到此這篇關于Django序列化組件Serializers使用詳解的文章就介紹到這了,更多相關Django序列化組件Serializers內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持本站!

版權聲明:本站文章來源標注為YINGSOO的內(nèi)容版權均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學習參考,不代表本站立場,如有內(nèi)容涉嫌侵權,請聯(lián)系alex-e#qq.com處理。

相關文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務

7x24全年不間斷在線

專屬顧問服務

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務熱線

關注
微信

關注官方微信
頂部