基本使用
-序列化 -对象,转成json格式 用drf的序列化组件 -定义一个类继承class BookSerializer(serializers.Serializer): -写字段,如果不指定source,字段名必须跟数据库字段名对应(source指定的值跟字段名不能重复) -source还可以指定方法 -publish=serializers.SerializerMethodField() def get_publish(self,obj): obj.publish #obj.authors.all() -Serializer -ModelSerializer class Meta: # 指定表模型 model = models.Book # 序列化所有字段 fields = ‘__all__‘ # 只想序列化title和id这俩字段 # fields = [‘title‘, ‘id‘] # exclude 和fields 不要连用 # exclude = [‘title‘] depth=1 -反序列化: -保存 ser=BookSer(data=传过来的字典) if ser.is_valid() ser.save() -取校验通过的数据: ser.data -修改 ser=BookSer(data=传过来的字典,instance=要修改的对象) if ser.is_valid() ser.save() else: errors=ser.errors # 如果想让publish字段显示出版社的名字 # publish = serializers.CharField(source=‘publish.name‘) # authors = serializers.SerializerMethodField() # def get_authors(self, obj): # author_list = obj.authors.all() # author_ser = AuthorSer(instance=author_list, many=True) # return author_ser.data
Django自带序列化组件
serializers(把对象序列化成json字符串)
from django.core import serializers
from django.core import serializers def test(request): book_list = Book.objects.all() ret = serializers.serialize("json", book_list) return HttpResponse(ret)
rest-framework序列化之Serializer
models部分
from django.db import models # Create your models here. class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.name class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
view部分
from rest_framework.views import APIView from rest_framework.response import Response from .models import * from django.shortcuts import HttpResponse from django.core import serializers from rest_framework import serializers <... 这一块代码最好新建一个 .py文件放在里面,这样的话看起来就不是那么乱了 class BookSerializers(serializers.Serializer): title=serializers.CharField(max_length=32) price=serializers.IntegerField() pub_date=serializers.DateField() publish=serializers.CharField(source="publish.name") #authors=serializers.CharField(source="authors.all") authors=serializers.SerializerMethodField() def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append(author.name) return temp #此处可以继续用author的Serializers, # def get_authors(self,obj): # ret=obj.authors.all() # ss=AuthorSerializer(ret,many=True) # return ss.data ...> class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.Serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(book_list,many=True) #many=True代表有多条数据,如果只有一条数据,many=False return Response(bs.data) # 序列化方式4: # ret=models.Book.objects.all().values(‘nid‘,‘title‘) # dd=list(ret) # return HttpResponse(json.dumps(dd))
注意:
source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source=‘authors.all‘))
如在模型中定义一个方法,直接可以在在source指定执行
class UserInfo(models.Model): user_type_choices = ( (1,‘普通用户‘), (2,‘VIP‘), (3,‘SVIP‘), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64) #视图 ret=models.UserInfo.objects.filter(pk=1).first() aa=ret.get_user_type_display() #serializer xx=serializers.CharField(source=‘get_user_type_display‘)
小结
# 1 变量名和source指定的值不能一样 # 2 source=‘publish.name‘还支持继续 . # 3 source 还支持方法(没用) # 4 支持写方法,如下 #方法一定传一个参数,是当前book对象 publish_dic=serializers.SerializerMethodField() def get_publish_dic(self,obj): # 猜,这个obj应该是谁,当前book对象 return {‘id‘:obj.publish.pk,‘name‘:obj.publish.name} 在线格式化json -https://www.json.cn/
rest-framework序列化之ModelSerializer
class BookSerializers(serializers.ModelSerializer): class Meta: model = models.Book # fields = "__all__" fields=[‘nid‘,‘title‘,‘authors‘,‘publish‘] # exclude=(‘nid‘,) #不能跟fields同时用 # depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层 publish=serializers.SerializerMethodField() def get_publish(self,obj): return obj.publish.name authors=serializers.SerializerMethodField() def get_authors(self,obj): ret=obj.authors.all() ss=AuthorSerializer(ret,many=True) return ss.data
生成hypermedialink(极少数)
class BookSerializers(serializers.ModelSerializer): class Meta: model = models.Book fields = "__all__" # 生成连接,直接查看出版社详情 publish = serializers.HyperlinkedIdentityField(view_name=‘ttt‘, lookup_field=‘publish_id‘, lookup_url_kwarg=‘pkk‘) authors=serializers.SerializerMethodField() def get_authors(self,obj): ret=obj.authors.all() ss=AuthorSerializer(ret,many=True) return ss.data #-------------- res=BookSerializers(ret,many=True,context={‘request‘: request}) #-------------- class Publish(APIView): def get(self,request,pkk): print(pkk) return HttpResponse(‘ok‘) #----路由--- url(r‘^publish/(?P<pkk>\d+)$‘, views.Publish.as_view(),name=‘ttt‘),
序列化组件之请求数据校验和保存功能
class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields="__all__" #———————— class BookView(APIView): def post(self, request): # 添加一条数据 print(request.data) bs=BookSerializers(data=request.data) if bs.is_valid(): bs.save() # 生成记录 return Response(bs.data) else: return Response(bs.errors)
class BookSerializer1(serializers.Serializer): title=serializers.CharField(error_messages={‘required‘: ‘标题不能为空‘}) #这种方式要保存,必须重写create方法
通过源码查看留的校验字段的钩子函数
#is_valid---->self.run_validation-(执行Serializer的run_validation)-->self.to_internal_value(data)---(执行Serializer的run_validation:485行) def validate_title(self, value): from rest_framework import exceptions raise exceptions.ValidationError(‘看你不顺眼‘) return value #全局 def validate(self, attrs): from rest_framework import exceptions if attrs.get(‘title‘)== attrs.get(‘title2‘): return attrs else: raise exceptions.ValidationError(‘不想等啊‘)
序列化组件源码分析
序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象 序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找) Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance) 再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs 当参数传过去,判断是方法就加括号执行,是属性就把值取出来
图书的增删查改resful接口与上面知识点的实例
视图层
from django.shortcuts import render, HttpResponse from django.http import JsonResponse # Create your views here. from django.views import View class Test(View): def dispatch(self, request, *args, **kwargs): # 写代码 obj = super().dispatch(request, *args, **kwargs) # 写代码 return obj def get(self, request, *args, **kwargs): return HttpResponse(‘cbv_get‘) def post(self, request, *args, **kwargs): return HttpResponse(‘cbv_post‘) user_list = [{‘id‘: 1, ‘name‘: ‘lqz‘, ‘age‘: 18}, {‘id‘: 2, ‘name‘: ‘egon‘, ‘age‘: 17}, {‘id‘: 3, ‘name‘: ‘xiaohou‘, ‘age‘: 16}] def users(request): response = {‘status‘: 100, ‘errors‘: None} if request.method == ‘GET‘: response[‘users‘] = user_list return JsonResponse(response, safe=False) if request.method == ‘POST‘: name = request.POST.get(‘name‘) age = request.POST.get(‘age‘) user_list.append({‘id‘: len(user_list) + 1, ‘name‘: name, ‘age‘: age}) # response[‘user‘] = {‘id‘:len(user_list),‘name‘: name, ‘age‘: age} response[‘msg‘] = ‘新增成功‘ return JsonResponse(response) def user(request, id): response = {‘status‘: 100, ‘errors‘: None} if request.method == ‘GET‘: id = int(id) response[‘user‘] = user_list[id] return JsonResponse(response) from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request # 基于drf写接口,写cbv class DrfTest(APIView): def get(self, request, *args, **kwargs): # request是封装之后的request了,原来的request是request._request print(type(request._request)) print(type(request)) # 问:当前request对象并没有这些属性,但是能打印出来,为什么? # 修改了getattr print(request.method) print(request.POST) print(request.GET) # 就相当于: print(request.query_params) print(request._request.GET) response = {‘status‘: 100, ‘errors‘: None} response[‘users‘] = user_list # 用drf的Response,可以通过请求客户端来判断返回数据格式是什么样的 return Response(response) # return JsonResponse(response) def post(self, request, *args, **kwargs): # post 提交的数据,urlencode,formdate,json格式,都能从data中取出来 name = request.data.get(‘name‘) # request.FILES print(name) return HttpResponse(‘ok‘) from app01 import models from app01.MySer import BookSerializer class Auth(): def authenticate(self,request): pass # 写一个获取所有图书的接口 class Books(APIView): authentication_classes=[Auth,] def get(self, request, *args, **kwargs): response = {‘status‘: 100, ‘msg‘: ‘成功‘} book_list = models.Book.objects.all() # 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True # 问?什么情况下many=False,instance=单个对象的时候 book_ser = BookSerializer(book_list, many=True) print(book_ser.data) response[‘books‘] = book_ser.data return Response(response) def post(self, request): response = {‘status‘: 100, ‘msg‘: ‘成功‘} # 提交的字典 # book = request.data # 传统方法,创建对象保存 # 新方法,通过序列化组件保存,必须用继承自ModelSerializer # data注意是data book_ser = BookSerializer(data=request.data) # is_valid提交的字段校验通过 if book_ser.is_valid(): book_ser.save() response[‘book‘] = book_ser.data else: response[‘msg‘] = book_ser.errors # return Response(book_ser.data) return Response(response) class Book(APIView): def get(self, request, id): response = {‘status‘: 100, ‘msg‘: ‘成功‘} book = models.Book.objects.filter(pk=id).first() book_ser = BookSerializer(book, many=False) response[‘book‘] = book_ser.data return Response(response) def put(self, request, id): response = {‘status‘: 100, ‘msg‘: ‘成功‘} book = models.Book.objects.filter(pk=id).first() # 修改的话,要把book对象传过来 book_ser = BookSerializer(data=request.data, instance=book) # is_valid提交的字段校验通过 if book_ser.is_valid(): # save既可以修改,又可以更新 book_ser.save() response[‘book‘] = book_ser.data else: response[‘msg‘] = book_ser.errors # return Response(book_ser.data) return Response(response) def delete(self,request,id): response = {‘status‘: 100, ‘msg‘: ‘删除成功‘} book = models.Book.objects.filter(pk=id).delete() return Response(response)
模板层
from django.db import models # Create your models here. from django.db import models # Create your models here. class Book(models.Model): title = models.CharField(max_length=32) price = models.IntegerField() pub_date = models.DateField() publish = models.ForeignKey("Publish") authors = models.ManyToManyField("Author") def test(self): return self.title + str(self.price) def __str__(self): return self.title class Publish(models.Model): name = models.CharField(max_length=32) email = models.EmailField() # def __str__(self): # return self.name # return str(self.pk) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # # def __str__(self): # return self.name
自己手动创建的序列化组件层
from rest_framework import serializers # from rest_framework.request import Request class AuthorSer(serializers.Serializer): id = serializers.CharField() name = serializers.CharField() age = serializers.CharField() # class BookSerializer(serializers.Serializer): # id = serializers.CharField() # # 通过source可以改名 # name = serializers.CharField(source=‘title‘) # price = serializers.CharField() # # xxx = serializers.CharField(source=‘test‘) # # 1 变量名和source指定的值不能一样 # # 2 source=‘publish.name‘还支持继续 . # # 3 source 还支持方法(没用) # # publish_name = serializers.CharField(source=‘publish.name‘) # # publish_id = serializers.CharField(source=‘publish.pk‘) # # 4 支持写方法,如下 # #方法一定传一个参数,是当前book对象 # publish_dic=serializers.SerializerMethodField() # def get_publish_dic(self,obj): # # 猜,这个obj应该是谁,当前book对象 # return {‘id‘:obj.publish.pk,‘name‘:obj.publish.name} # authors=serializers.SerializerMethodField() # # def get_authors(self,obj): # # # 所有作者queryset对象 # # author_list=obj.authors.all() # # ll=[ {‘name‘:author.name,‘id‘:author.pk} for author in author_list] # # return ll # def get_authors(self,obj): # # 所有作者queryset对象 # author_list=obj.authors.all() # author_ser=AuthorSer(instance=author_list,many=True) # return author_ser.data # ModelSerializer跟表模型绑定的序列化 from app01 import models class BookSerializer(serializers.ModelSerializer): class Meta: # 指定表模型 model = models.Book # 序列化所有字段 fields = ‘__all__‘ # 只想序列化title和id这俩字段 # fields = [‘title‘, ‘id‘] # exclude 和fields 不要连用 # exclude = [‘title‘] # 深度,表示连表的深度 # 不建议使用:下几层要取得参数不能控制,官方建议不要超过10,我给你的建议不要超过3 # depth=1 # 全取出来之后,可以在后面覆盖之前的值 # 如果想让publish字段显示出版社的名字 # publish = serializers.CharField(source=‘publish.name‘) # authors = serializers.SerializerMethodField() # def get_authors(self, obj): # author_list = obj.authors.all() # author_ser = AuthorSer(instance=author_list, many=True) # return author_ser.data title = serializers.CharField(max_length=6, min_length=3, error_messages={‘max_length‘: ‘太长了‘}) # 也有局部钩子和全局钩子 def validate_title(self, value): from rest_framework import exceptions print(value) if value.startswith(‘sb‘): raise exceptions.ValidationError(‘不能以sb开头‘) return value # def validate_title(self, value): # from rest_framework import exceptions # raise exceptions.ValidationError(‘看你不顺眼‘) # return value
路由
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^users/‘, views.DrfTest.as_view()), # 在这写的实际上就是as_view()内view的内存地址 url(r‘^books/‘, views.Books.as_view()), url(r‘^book/(?P<id>\d+)‘, views.Book.as_view()), ]
原文地址:https://www.cnblogs.com/596014054-yangdongsheng/p/10228812.html
时间: 2024-10-25 08:20:33