drf序列化器serializers.SerializerMethodField()的用法
问题描述:
为什么DRF中有时候返回的json中图片是带域名的,有时候是不带域名的呢?
解析:
带域名的结果是在view中对模型类序列化的,DRF在序列化图片的时候 会检查上下文有没有request,如果有,就给图片加上域名,
比如说我们视图用的是apiview():
我们需要序列化数据的时候,加 context={"request":request}
TestSerilaizer(instance=instance, context={"request":request})
然后这样序列化器就取到了request对象,然后你再测试下图片url即可
还有一种情况,在序列化器里调用序列化器的时候,也会碰到这种情况,当然也必须要这样解决,
goods_json = GoodsSerializer(good_ins, many=False, context={'request': self.context['request']}).data #注意具体语法
我再说几种传参的方法,这几种方法在开发过程中也会经常的遇到,
在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
serializer = AccountSerializer(account, context={'request': request})
解析,如果是apiview,你视图函数里就写第一行格式,确保序列化器里可以取到requsts对象,当然如果视图函数继承的非apiview,那么可以忽略,
我们可以在序列化器里取很多参数方便我们使用,如
def validate(self, attrs):#在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:
# request、format、view,这三个数据对象可以在定义序列化器时使用
mobile = self.context['view'].kwargs['mobile']
这样就可以取到url里的mobile参数,来我们接着看,
在视图里这样取也可以,比如当我们重写视图的get方法时:我们这样取pk得值
from rest_framework.generics import ListAPIView
class NewGoodsView(ListAPIView):
serializer_class = GoodeInfoSerializer
queryset = GoodInfo.objects.all()
def get(self,request,*args,**kwargs):
goods = GoodInfo.objects.filter(type_id=kwargs['pk']).order_by('-id')[:2]
ser = self.get_serializer(goods,many=True)
return Response(ser.data)
然后看看下面这张截图,当访问商品详情时 点击量+1,
然后再继续看看,只要是我们请求后台时前端请求header头中携带token认证,然后我们在后台就可以用request 取到当前的用户对象,如
class MyCartInfoView(ListAPIView):
'''
我的购物车页面
'''
serializer_class = CartInfoSerializer
queryset = Cart.objects.all()
def get_queryset(self):
return self.queryset.filter(user = self.request.user,selected=True)
下面,我再介绍四种我们经常会用到的方法
get_objects() :
接着看下面,我们在URL中并没有携带参数,这样的话视图找不到PK会抛出异常,当我们重写get_objects() 方法后,
class UserDetalView(RetrieveAPIView):
'''
个人中心信息展示
'''
serializer_class = UserDetailSerializer
permission_classes = (IsAuthenticated,)
# 重写get_object方法,返回用户指定信息
def get_object(self):
return self.request.user
解析:get_objects()
返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在视图中可以调用该方法获取详情信息的模型类对象。
若详情访问的模型类对象不存在,会返回404。
get_queryset():
返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:
get_serializer(self, args, *kwargs)
返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。
class CartCountView(GenericAPIView):
'''
detail页面购物车数量渲染
'''
serializer_class = CartCountSerializer
queryset = Cart.objects.all()
def get(self,request):
ser = self.get_serializer(self.get_queryset().filter(user=request.user),many=True)
count = len(ser.data)
return Response({'data':count})
get_serializer_class(self)
返回序列化器类,默认返回serializer_class
,可以重写,例如:三级联动的实现,
先看看序列化器,
class AreaSerializer(serializers.ModelSerializer):
'''
行政区信息序列化器
'''
class Meta:
model = Area
fields = ('id', 'name') class SubAreaSerializer(serializers.ModelSerializer):
'''
子集行政区信息序列化器
'''
subs = AreaSerializer(read_only=True,many=True)
class Meta:
model = Area
fields = ('id', 'name', 'subs')
来看看视图,
class AreaViewSet(CacheResponseMixin,ReadOnlyModelViewSet):
# 关闭分页,因为高级视图集默认是有分页操作的,而我们这里前端页面选择省市县,是不需要分页的
pagination_class = None
# queryset = Area.objects.all()
# serializer_class = AreaSerializer '''
list:返回所有的省份信息
retrieve:返回特定省或市下的下属城市
'''
def get_queryset(self):
'''
返回视图使用的查询集,
是列表视图与详情视图获取数据的基础,
默认返回queryset属性
'''
if self.action == 'list':
return Area.objects.filter(parent=None)
else:
return Area.objects.all() def get_serializer_class(self):
if self.action == 'list':
return AreaSerializer
else:
return SubAreaSerializer
来看看url
from django.conf.urls import url
from . import views
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('areas',views.AreaViewSet,base_name='area') urlpatterns = [ ] urlpatterns += router.urls
其实能坚持看到文章末尾的小同学们,你会发现末尾有彩蛋,
drf模型序列化器默认仅返回数据库中已存在字段,如果想新增输出字段,改如何操作?
例如:输出用户角色时,顺便输出当前角色总共有多少用户.
先举个例子:
class Role(models.Model):
"""角色表,一的一方"""
name = models.CharField(max_length=30, unique=True, verbose_name='角色名称') # 媒体运营,广告运营,活动运营,财务,技术,唯一,必填
desc = models.CharField(max_length=100, null=True, blank=True, verbose_name='角色描述') # 非必填 class Meta:
db_table = 'tb_role'
verbose_name = '角色'
verbose_name_plural = verbose_name def __str__(self):
"""控制对象输出内容"""
return self.name class User(BaseModel):
"""用户表,多的一方"""
account = models.CharField(max_length=30, unique=True, verbose_name='登录账户') # 必填,唯一
password = models.CharField(max_length=100, null=True, blank=True, default='',
verbose_name='登录密码') # 非必填,默认888888,长度100是为了以后加密扩展
username = models.CharField(max_length=30, null=True, blank=True, verbose_name='用户名称') # 非必填
role = models.ForeignKey(Role, on_delete=models.CASCADE, related_name='user', verbose_name='角色') class Meta:
db_table = 'tb_user'
verbose_name = '用户'
verbose_name_plural = verbose_name def __str__(self):
"""控制对象输出内容"""
return self.account
接着看序列化器,
class RoleModelSerializer(serializers.ModelSerializer):
"""角色模型序列化器"""
user_count = serializers.SerializerMethodField(label='用户数量') # 新增数据库不存在字段用户数量 class Meta:
model = Role
fields = ['id', 'name', 'desc', 'user_count'] def get_user_count(self, obj):
"""
返回当前角色用户数量
固定写法,obj代表Role实例对象,模型类配置了反向引用user代表当前角色用户
"""
number = obj.user.count()
return number
注意:
user_count 字段在数据库中不能存在,下面写方法的时候前面加 get_ 就可以,这样就得到我们需要的数据了。
在此方法里需要调用序列化器,我们直接调用即可,举例:
ad_goods = serializers.SerializerMethodField() #位于中间部分goods商品的img大图片显示 def get_ad_goods(self, obj):
goods_json = {}
ad_goods = IndexAd.objects.filter(category_id=obj.id,) #过滤goods在广告表中的数据
if ad_goods:
good_ins = ad_goods[0].goods #取一条
goods_json = IndexGoodsSerializer(good_ins, many=False, context={'request': self.context['request']}).data
return goods_json
HiddenField()
HiddenField的值不依靠输入,而需要设置默认的值,不需要用户自己post数据过来,也不会显式返回给用户,最常用的就是user!!
我们在登录情况下,进行一些操作,假设一个用户去收藏了某一门课,那么后台应该自动识别这个用户,然后用户只需要将课程的id post过来,那么这样的功能,我们配合CurrentUserDefault()实现。
下面是一个用户留言功能的实现:
class LeavingMessageSerializer(serializers.ModelSerializer):
'''
用户留言
'''
# 获取当前登录的用户
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
#read_only:只返回,post时候可以不用提交,format:格式化输出
add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')
class Meta:
model = UserLeavingMessage
fields = ("user", "message_type", "subject", "message", "file", "id" ,"add_time")
大家有什么问题,尽可以在下方留言。
drf序列化器serializers.SerializerMethodField()的用法的更多相关文章
- drf序列化器与反序列化
什么是序列化与反序列化 """ 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 """ drf序列化与反序列化 &qu ...
- DRF序列化器
序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成字典 ...
- DRF 序列化器-Serializer (2)
作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...
- drf序列化器的实例
应用目录结构: views.py from django.shortcuts import render # Create your views here. from django.views imp ...
- DRF序列化器的使用
序列化器的使用 序列化器的使用分两个阶段: 在客户端请求时,使用序列化器可以完成对数据的反序列化. 在服务器响应时,使用序列化器可以完成对数据的序列化. 序列化的基本使用 使用的还是上一篇博文中使用的 ...
- 对drf序列化器的理解
序列化: 将对象的状态信息转换为可以存储或传输的形式的过程.(百度定义) 对应到drf中,序列化即把模型对象转换为字典形式, 再返回给前端,主要用于输出 反序列化: 把其他格式转化为程序中的格式. 对 ...
- 关于定义序列化器时,read_only和write_only有什么作用
关于序列化和反序列化 在谈论前,先说一下序列化和反序列化,这两个概念最初是在学习json的时候提出来的,回头来看,其实可以用最初的理解就可以了 序列化就是将对象转化方便传输和存储字节序列,例如js ...
- 经历了源码的痛苦,掌握DRF的核心序列化器
目录 DRF的核心--序列化器 序列化器 什么是序列化和反序列化? 序列化 序列化demo 字段类型 字段参数 序列化自定制返回字段 方法一:在序列化类(serializers.py)中写 方法二:在 ...
- DRF框架之 serializers 序列化组件
1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers ...
随机推荐
- Linux实战教学笔记23:Inotify事件监控工具
第二十三节 inotify事件监控工具 标签(空格分隔): Linux实战教学笔记-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品,允许转载, ...
- Mask_rcnn openpose realsense
cd /home/luo/Desktop/MyFile/Mask_RCNN_Openpose_Realsense python realsense_mask_openpose_2019032601.p ...
- SQLSERVER Tempdb的作用及优化
tempdb 系统数据库是可供连接到 SQL Server 实例的所有用户使用的全局资源.tempdb 数据库用于存储下列对象:用户对象.内部对象和版本存储区. 用户对象 用户对象由用户显式创建.这些 ...
- code1173 最优贸易
先正向从1点出发SPFA,获得min[i],就是到达i点能最低购买到的价格,(起始点到i的路上经过的最小值) 然后反向(将图反向),从n点开始SPFA,获得max[i],就是从i点到终点能够卖出的最大 ...
- 洛谷 P1103 书本整理(动规)
洛谷 P1103 书本整理 题目描述 Frank是一个非常喜爱整洁的人.他有一大堆书和一个书架,想要把书放在书架上.书架可以放下所有的书,所以Frank首先将书按高度顺序排列在书架上.但是Frank发 ...
- Python爬虫实战二之爬取百度贴吧帖子
大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 前言 亲爱的们,教程比较旧了,百度贴吧页面可能改版,可能代码不 ...
- xStream完美转换XML、JSON(转)
xStream框架 xStream可以轻易的将Java对象和xml文档相互转换,而且可以修改某个特定的属性和节点名称,而且也支持json的转换: 前面有介绍过json-lib这个框架,在线博文:htt ...
- jdk1.7 环境变量配置
Windows系统中设置环境变量如下图右击“我的电脑”,选择“属性”. 点击“高级”选项卡,选择“环境变量”. 在“系统环境变量”中设置上面提到的3个环境变量,如果变量已经存在就选择“编辑”,否则选 ...
- Win10安装Mongodb,并配置成服务
好吧,今天突然发现新买的surface上没有安装mongodb,然后想着安装一下,顺便记录一下,虽说安装过程很简单 一:下载安装,然后拷贝到C盘根目录,这个就不多说了,比QQ都简单. 二:把bin文件 ...
- [GO]channel实现同步
goroutine运行在相同的地址空间,因此访问共享内存必须 做好同步.goroutine奉行通过通信来共享内存,而不是共享内存通信 它跟map一样,使用make来创建,它是一个引用 ,而不是值传递 ...