序列化器-serializer

简单使用

1、创建一个表模型

fromdjango.dbimportmodelsclassBooks(models.Model):title = models.CharField(verbose_name='书名', max_length=32)    publish = models.CharField(verbose_name='出版社', max_length=32)    price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2)

2、新建一个py文件,写一个序列化的类,继承Serializer

3、在类中写要序列化的字段,想序列化那个字段,就在类中写那个字段

fromrest_frameworkimportserializersclassBooksSerializer(serializers.Serializer):title = serializers.CharField()    publish = serializers.CharField()    price = serializers.DecimalField()

4、在视图类中使用,导入——》实例化得到序列化对象,把要序列化的对象传入

5、序列化的对象.data——》是一个字典

6、把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse

fromrest_framework.viewsimportAPIViewfromrest_framework.requestimportRequestfromapp01.modelsimportBooksfromapp01.serimportBooksSerializerclassBookView(APIView):defget(self, request, pk):# 响应信息response_msg = {'status':200,'message':'查询成功'}# 获取要序列化的对象book = Books.objects.filter(pk=pk).first()# 要序列化谁就把谁传到序列化类去book_ser = BooksSerializer(book)# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturnResponse(response_msg)# urls.pyre_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),

7、如果要被序列化的是包含多条数据的查询集queryset,可以通过添加many=True参数

fromrest_framework.viewsimportAPIViewfromrest_framework.responseimportResponsefromapp01.modelsimportBooksfromapp01.serimportBooksSerializerclassBooksView(APIView):defget(self, request):# 响应信息response_msg = {'status':200,'message':'查询成功'}        books = Books.objects.all()# 要序列化谁就把谁传到序列化类去book_ser = BooksSerializer(books, many=True)# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturnResponse(response_msg)# urls.pyre_path(r'^books/', views.BookView.as_view()),

高级使用

source

1、可以修改字段名字

classBooksSerializer(serializers.Serializer):xxx = serializers.CharField(source='title')# 相当于——》xxx = Books.title# 响应{"status":200,"message":"查询成功","data": {"xxx":"魔道祖师"————》响应的字段名被修改了    }}

2、可以跨表查询

classBookSerializer(serializers.Serializer):publish_email = serializers.CharField(source='publish.email')# 相当于——》publish_email = Book.publish.email 连表查询publish表的email字段# 响应{"status":200,"message":"查询成功","data": {"publish_email":"modao@163.com"}}

3、可以执行方法

# models.pyclassBook(models.Model):title = models.CharField(max_length=32)    price = models.IntegerField()    pub_date = models.DateTimeField()    publish = models.ForeignKey("Publish", on_delete=models.CASCADE, null=True)    authors = models.ManyToManyField("Author")deffunc(self):return'666666'# ser.pyclassBookSerializer(serializers.Serializer):msg = serializers.CharField(source='func')# msg = Book.func  ——》调用Book类中的func()方法的返回值# 响应{"status":200,"message":"查询成功","data": {"msg":"666666"}}

**SerializerMethodField( ) **

它需要有一个配套的方法,方法名叫做get_字段名,返回值就是要显示的东西

classBookSerializer(serializers.Serializer):authors = serializers.SerializerMethodField()defget_authors(self, instance):# instance ——》 Book对象authors = instance.authors.all()# 取出所有作者author_list = []forauthorinauthors:            author_list.append({'name': author.name,'age': author.age})returnauthor_list

通用参数

read_only:(只读)表明该字段仅用于序列化输出,默认False,如果设置成True,响应中可以看到该字段,修改时,不需要传该字段

write_only:(只写)表明该字段仅用于反序列化输入,默认False,如果设置成True,响应中看不到该字段,修改时,该字段需要传

fromrest_frameworkimportserializersclassBooksSerializer(serializers.Serializer):title = serializers.CharField(read_only =True)# 响应中能看到改字段,修改不需要传值publish = serializers.CharField(write_only =True)# 响应中看不到改字段,修改需要传值price = serializers.DecimalField()# 还有参数如下:required表明该字段在反序列化时必须输入,默认Truedefault反序列化时使用的默认值allow_null表明该字段是否允许传入None,默认Falsevalidators该字段使用的验证器error_messages包含错误编号与错误信息的字典

三、反序列化数据校验

当使用序列化器对数据进行反序列化时,就需要对数据进行校验了,只有校验成功的数据才能被保存成模型类对象

将要校验的数据传入序列化器中并实例化:obj = BooksSerializer(data=request.data),调用is_valid()方法校验,校验成功返回True,失败返回False。

失败,可以通过序列化器对象的errors获取错误信息(字典)

成功,可以公共序列化对象的validated_data属性获取数据。

校验方法有:局部钩子,全局钩子,validators,和序列化类型和字段属性也是

字段属性

max_length 最大长度

min_lenght 最小长度

allow_blank 是否允许为空

trim_whitespace 是否截断空白字符

max_value 最小值

min_value 最大值

局部钩子

在序列化器类中创建局部钩子:validate_字段名,并且接收一个参数

# ser.pyclassBooksSerializer(serializers.Serializer):title = serializers.CharField()    publish = serializers.CharField()    price = serializers.DecimalField(max_digits=5, decimal_places=2)# 局部钩子对price字段校验defvalidate_price(self, data):iffloat(data) >20:# 校验成功就通过returndataelse:# 校验失败就抛异常raiseValidationError('价格太低')

全局钩子

全局钩子:validate( ), 接收一个参数,

同时对多个字段进行比较验证

# ser.pyclassBooksSerializer(serializers.Serializer):title = serializers.CharField()    publish = serializers.CharField()    price = serializers.DecimalField(max_digits=5, decimal_places=2)defvalidate(self, validate_data):title = validate_data.get('title')    publish = validate_data.get('publish')ifnottitle == publish:returnvalidate_dataelse:raiseValidationError('书名和出版社不能一致')

validators

使用字段的validators=[func],来校验

# ser.py# 校验函数defcheck_price(data):iffloat(data) >10:returndataelse:raiseValidationError('价格太低')classBooksSerializer(serializers.Serializer):title = serializers.CharField()    publish = serializers.CharField()    price = serializers.CharField(validators=[check_price])# 配置

四、序列化器操作数据

查询所有

# views.pyclassBooksView(APIView):defget(self, request):# 响应信息response_msg = {'status':200,'message':'查询成功'}# 获取所有数据books = Books.objects.all()# 把数据谁传到序列化器中book_ser = BooksSerializer(instance=books, many=True)# 序列化多条需要加 many=True# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturnResponse(response_msg)# urls.pypath('books/', views.BooksView.as_view()),

查询单条

# views.pyclassBookView(APIView):defget(self, request, pk):# 响应信息response_msg = {'status':200,'message':'查询成功'}# 获取要序列化的对象book = Books.objects.filter(pk=pk).first()# 要序列化谁就把谁传到序列化器中book_ser = BooksSerializer(instance=book)# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturnResponse(response_msg)# urls.pyre_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),

新增数据

新增数据需要在序列化器中重写create( ) 方法:

注意没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,调用save()方法的时候,update()被调用。

# views.pyclassBookView(APIView):defpost(self, request):# 响应信息response_msg = {'status':201,'message':'增加成功'}# 修改才有instance,新增没有instance,只有databook_ser = BooksSerializer(data=request.data)# 校验字段ifbook_ser.is_valid():            book_ser.save()# 需要在序列化器中重写create()方法# 保存成功把原数据返回response_msg['data'] = book_ser.dataelse:            response_msg['status'] =202response_msg['message'] ='数据校验失败'response_msg['data'] = book_ser.error_messagesreturnResponse(response_msg)# ser.pyclassBooksSerializer(serializers.Serializer):title = serializers.CharField()    publish = serializers.CharField()    price = serializers.DecimalField(max_digits=5, decimal_places=2)# 重写createdefcreate(self, validated_data):# validated_data——>传入的新增数据instance = Books.objects.create(**validated_data)# instance——> 新增的字段对象,需要返回returninstance# urls.pypath('book/', views.BookView.as_view()),

修改数据

修改数据需要在序列化器中重写update( ) 方法:

# views.pyclassBookView(APIView):defput(self, request, pk):# 响应信息response_msg = {'status':200,'message':'修改成功'}# 获取需要修改的字段对象book = Books.objects.filter(pk=pk).first()# 将字段对象和修改数据添加到序列化器中book_ser = BooksSerializer(instance=book, data=request.data)# 校验数据ifbook_ser.is_valid():            book_ser.save()# 需要在序列化器中重写update()方法response_msg['data'] = book_ser.dataelse:            response_msg['status'] =202response_msg['message'] ='数据校验失败'response_msg['data'] = book_ser.error_messagesreturnResponse(response_msg)# urls.pyre_path('book/(?P<pk>\d+)', views.BookView.as_view()),

删除数据

# views.pyclassBooksView(APIView):defdelete(self, request, pk):# 响应信息response_msg = {'status':200,'message':'删除成功'}# 删除数据Books.objects.filter(pk=pk).delete()returnResponse(response_msg)# urls.pyre_path('book/(?P<pk>\d+)', views.BooksView.as_view()),

五、模型类序列化器

DRF提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。

ModelSerializer与常规的Serializer相同,但是提供了:

基于模型类自动生成一系列字段

基于模型类自动为Serializer生成validators,比如unique_together

包含默认的create( ) 和update( )。

实例:

classBookSerializer(serializers.ModelSerializer):classMeta:model = Book# 指明参照那个模型类fields ='__all__'# 为模型类的那些字段生成

字段操作

1、可以使用fields来明确字段,__all__表示包含所以字段,具体那些字段->fields = ('title','price')

2、exclude表示排除那些字段,不能和fields一起写——>exclude = ('price',)

3、额外参数extra_kwargs,给字段添加额外的参数

classBookSerializer(serializers.ModelSerializer):classMeta:model = Book# 指明参照那个模型类fields ='__all__'# 为模型类的那些字段生成# 类似于  title = serializers.CharField(read_only = True)extra_kwargs = {'title': {'read_only':True},        }

六、源码分析many=True

当我们需要查询多条数据时就需要在实例化序列化器的时候传many=True

book_ser = BooksSerializer(instance=books, many=True)# 查询多条book_one_ser = BooksSerializer(instance=book)# 查询单条print(type(book_ser))#<class 'rest_framework.serializers.ListSerializer'>print(type(book_one_ser))#<class 'app01.ser.BookModelSerializer'># 对象的生成-->先调用类的__new__方法,生成空对象,如果many=True,生成ListSerializer对象,反之生成Serializer对象# 类的__new__方法控制对象的生成def__new__(cls, *args, **kwargs):# 如果many=True,就会自动创建ListSerializer类ifkwargs.pop('many',False):returncls.many_init(*args, **kwargs)returnsuper().__new__(cls, *args, **kwargs)

USB Microphone https://www.soft-voice.com/

Wooden Speakers  https://www.zeshuiplatform.com/

亚马逊测评 www.yisuping.cn

深圳网站建设www.sz886.com

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容