日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DRF 序列化组件

發布時間:2024/9/5 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DRF 序列化组件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一. DRF序列化

  django自帶有序列化組件,但是相比rest_framework的序列化較差,所以這就不提django自帶的序列化組件了。

  首先rest_framework的序列化組件使用同from組件有點類似,當反序列化前端返回的數據之后,需要先調用is_valid進行校驗,其中也有局部鉤子validate_字段名,全局鉤子validate,is_valid校驗過后才可調用.data與.errors。

  rest_framework有兩種序列化方式,分別是繼承Serializer和ModelSerializer,如果序列化的數據是多條時,一定要指定many=True,不然會報錯。many=True與False的區別是前者返回列表套字典,而后者只有一個字典,即就一條數據。

from rest_framework.serializers import Serializer, ModelSerializer

?1.1 繼承Serializer的序列化

  models.py中代碼如下:

from django.db import models# Create your models here.class Book(models.Model):title = models.CharField(max_length=32)price = models.IntegerField()# db_constraint=False時,一對多表只存在邏輯上的關系,處理數據無需考慮外鍵關系,但是依舊可以正常使用ORM# on_delete在django1版本中默認是CASCADE,即級聯刪除。on_delete有四種選擇,SET_NULL即外鍵對應一表# 數據刪除時,將該字段設置為空,需要設置null=True或default# related_name='反向查詢的依據名字'# 外鍵對應的表點該依據名字.all來查詢多關系表的數據,不需要表名小寫+_set.all來獲取publish = models.ForeignKey("Publish", related_name='books', db_constraint=False, on_delete=models.SET_NULL, null=True)authors = models.ManyToManyField("Author", db_constraint=False)def __str__(self):return self.titleclass Publish(models.Model):name = models.CharField(max_length=32)email = models.EmailField()def __str__(self):return self.nameclass Author(models.Model):name = models.CharField(max_length=32)age = models.IntegerField()def __str__(self):return self.name

  序列化類BookSerializer如下:

class BookSerializer(serializers.Serializer):title = serializers.CharField(max_length=32)price = serializers.IntegerField()# source的作用很強大,其中的值相當于self.publish.name,# 當有字段使用choices屬性時,可以指定source='get_字段名_display'來直接獲取對應的值# source 如果是字段,會顯示字段,如果是方法,會執行方法,不用加括號publish = serializers.CharField(source='publish.name')# 可以指定一個函數,函數名固定get_字段名,函數return的值就是該字段的值# read_only是反序列化時不傳,write_only是序列化時不顯示author_detail = serializers.SerializerMethodField(read_only=True)# 該函數return的值就是author_detail字段的值def get_author_detail(self, book_obj):authors = book_obj.authors.all()# 函數內部可以直接調用其他序列化類return AuthorSerializer(authors, many=True).data# 局部鉤子def validate_title(self, value): # value是當前的title的值from rest_framework import exceptionsif 'h' in value:# 這是將校驗未通過的信息存入序列化obj.errors中raise exceptions.ValidationError('h是不可能h的')return value# 全局鉤子def validate(self, attrs): # attrs是包含了所有字段及數據的字典from rest_framework import exceptionsif attrs.get('title') == attrs.get('price'):return attrselse:raise exceptions.ValidationError('書名怎么和價格一樣')

  注意,無論是局部鉤子還是全局鉤子函數,都要序列化對象走is_valid方法時才會觸發,而且全局要所有需要序列化的字段通過校驗才會觸發。

  上述需要的AuthorSerializer如下:

# 作者Author序列化類 class AuthorSerializer(serializers.Serializer):name = serializers.CharField(max_length=32)age = serializers.IntegerField()

  在表中寫入數據后,在視圖views.py中寫CBV繼承ListAPIView:

from rest_framework.generics import ListAPIView from app01 import models from app01 import app01serializers # Create your views here.class BookAPIView(ListAPIView):queryset = models.Book.objectsserializer_class = app01serializers.BookSerializer

  然后開路由:

from django.conf.urls import url from django.contrib import admin from app01 import viewsurlpatterns = [url(r'^admin/', admin.site.urls),url(r'^books/', views.BookAPIView.as_view()), ]

  隨后用postman測試該接口:

  這里要注意,如果是前端往后端提交post請求創建新的數據時,要反序列化,然后調用is_valid校驗數據,之后才能調用.dada.errors。因為繼承Serializer是沒有指定表的,我們需要在對應的序列化類中重寫create方法,將.dada當create的參數傳入,然后create中寫保存的邏輯,如果涉及到多表,那么要全靠自己邏輯去寫了,在視圖中執行is_valid前將其他表需要的參數取出執行保存操作即可。

  反序列時需要把將參數指定給data:

bs=BookSerializer(data=request.data)

?  如果intence參數和data參數都給予了值,那么會執行更新操作:

def put(self, request, pk):book_obj = models.Book.objects.filter(pk=pk).first()bs=BookSerializers(data=request.data, instance=book_obj)if bs.is_valid():bs.save() # updatereturn Response(bs.data)else:return Response(bs.errors)

?1.2 繼承ModelSerializer的序列化

  繼承Modelserializer的序列化比較方便,因為不需要逐個寫字段及字段的類型等。

  序列化類如下:

class BookSerializer(serializers.ModelSerializer):# 生成publish_detail的第三種方式publish = PublishSerializer()class Meta:model = models.Book# fields = '__all__' 所有字段序列化,不過一般我們不會使用該方式# 一般采用下列方式,里面可以填表擁有的字段,# 也可以寫該表中外鍵字段、多對多表正向或反向對應點語法采用的字段# 其中反向查詢時我們一般采用.表名小寫的方式,可以在Foreign中設置字段related_name='反向查詢點語法后的名稱'# 比如Book表中外鍵字段publish設置屬性related_name='books',那么Publish表反向查詢書籍時,# .books_all()即可拿到該出版社出版的所有書籍對象(不然要寫.book_set.all())fields = ['title', 'price', 'publish', 'author_detail']# exclude=('title',) #拿出除了title的所有字段,不能跟fields同時用# depth = 1 #深度控制,寫 幾 往里拿幾層,層數越多,響應越慢,官方建議0--10之間,個人建議最多3層

  繼承ModelSerializer的類也可以寫全局鉤子、局部鉤子,以及對字段進行處理,不過已訂購要寫在class Meta的外面。

  fields中可以寫模型表帶有的字段,包含外鍵字段及ManyToMany字段,當指定了related_name時,反向查詢的表可以寫related_name指定的名字來訪問另一張表。

  這里提一嘴,rest_framework提供了深度屬性depth,但是不建議使用,因為不可控性太強。一般涉及到多表時,我們都在模型表中進行,比如此處的author_detail,是多對多關系表中book對應的所有author對象,我們在Book模型表中增加以下方法:

@property def author_detail(self):result_list = []authors = self.authors.all()for author in authors:dic = {'name': author.name, 'age': author.age}result_list.append(dic)return result_list

  上面publish也可以在模型表中定義,比如寫publish_detail:

# 生成publish_detail方式一 @property def publish_detail(self):publish_obj = self.publishreturn {'name': publish_obj.name, 'email': publish_obj.email}# 生成publish_detail方式二 @property def publish_detail(self):from app01 import app01serializerspublish_obj = self.publishreturn app01serializers.PublishSerializer(publish_obj).data

  然后將序列化類中的publish改為publish_detail,用postman測試接口:

  結果是一樣的,繼承ModelSerializer因為需要指定模型表,所有不需要重寫create方法,直接調用.save方法即可。

1.3 模型層中參數的補充

  比如當我們創建外鍵關系與多對多關系表時,django 1.x版本默認都是級聯刪除的,即on_delete=CASCADE,而django 2.x版本需要自己指定。

  on_delete一共有四個值可以選擇:

1. on_delete = models.SET_NULL # 關聯表字段刪除后,該ForeignKey字段的值置為空,需要設置null=True或者是設置default 2. on_delete = models.SET_DEFAULT # 關聯表字段刪除后,該ForeignKey字段的值置為默認值,需要設置default字段 3. on_delete = models.DO_NOTHING # 關聯表字段刪除后,該ForeignKey字段的值不變 4. on_delete = models.CASCADE # 關聯表字段刪除后,級聯刪除

?  Foreign與ManyToMany字段還有db_constraintrelated_name字段。指定db_constraint=False時,一對多的表只存在邏輯上的關系(此時數據庫如navicat中表關系圖它們之間的線會斷開),處理數據無需考慮外鍵關系,不過依舊可以使用ORM正常操作正反向查詢等。

  指定related_name字段時,反向查詢無需按表名小寫的方式,直接點該related_name定義的字段即可。舉例,比如Book表與Author表一對多,外鍵在Book表中,那么Author查詢Book表的數據就是反向查詢,需要author_obj.book_set.all()獲取作者對應的所有書籍數據。這時指定related_name='books',那么只需采用author_obj.books.all()即可。

  如果不清楚可以再看看該博客:https://www.cnblogs.com/liuqingzheng/articles/9766376.html

?

轉載于:https://www.cnblogs.com/maoruqiang/p/11228922.html

總結

以上是生活随笔為你收集整理的DRF 序列化组件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。