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=‘888888‘,
                                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")

原文地址:https://www.cnblogs.com/zbllly/p/10336678.html

时间: 2024-08-27 21:03:23

drf序列化器serializers.SerializerMethodField()的用法的相关文章

drf序列化器与反序列化

什么是序列化与反序列化 """ 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 """ drf序列化与反序列化 """ 序列化:Model类对象转换为字符串用于传输 反序列化:字符串转换为Model类对象用于使用 """ Model类 创建数据库:终端 >: mysql -uroot -p密码 >: create database 数据库名 charse

drf序列化器的实例

应用目录结构: views.py from django.shortcuts import render # Create your views here. from django.views import View from django.http import JsonResponse, QueryDict from bookset.models import BookInfo #导入序列化列 from .serializers import BookInfoSerializer #####

DRF序列化器的使用

序列化器的使用 序列化器的使用分两个阶段: 在客户端请求时,使用序列化器可以完成对数据的反序列化. 在服务器响应时,使用序列化器可以完成对数据的序列化. 序列化的基本使用 使用的还是上一篇博文中使用的数据库 先查询出一个学生对象 from students.models import Student student = Student.objects.get(id=3) 构造序列化器对象 from .serializers import StudentSerializer serializer

关于定义序列化器时,read_only和write_only有什么作用

关于序列化和反序列化 ? 在谈论前,先说一下序列化和反序列化,这两个概念最初是在学习json的时候提出来的,回头来看,其实可以用最初的理解就可以了 序列化就是将对象转化方便传输和存储字节序列,例如json.dumps就是序列化(狭义的序列化,将字典转化为json字符串),这样得到的json字符串不仅直接可以在其他语言使用(跨平台比较好),而且可以在前后端进行传输交互(drf序列化器) 反序列化恰恰相反,而是将字节序列转化为对象,json.loads是将json字符串转化为字典,是狭义的反序列化(

DRF框架之 serializers 序列化组件

1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers 分为:第一种 Serializer   第二种 ModelSerializer 第一种用法之 Serializer from django.db import models # Create your models here. class Book(models.Model): nid = mod

drf的序列化器

三流 import sys #标准输出流 sys.stdout.write('123\n') sys.stdout.write('456\n') #标准输入流 res=sys.stdin.readline() print(res) #标准错误流:将括号内数据作为错误输出 sys.srderr.write('abc\n') sys.stderr.write('xyz\n) 注意:每个流之间为异步提交,流内为同步提交. JSON文件格式 JSON 值可以是: 数字(整数或浮点数) 字符串(在双引号中

DRF框架之Serializer序列化器的序列化操作

在DRF框架中,有两种序列化器,一种是Serializer,另一种是ModelSerializer. 今天,我们就先来学习一下Serializer序列化器. 使用Serializer序列化器的开发步骤: 1. 定义Serializer序列化器 首先,我们要在子应用中,创建见一个serializers.py文件,用来编写Serializer序列化器代码. from rest_framework import serializers # 定义序列化器 class BookInfoSerializer

DRF项目之通过业务逻辑选择数据集和序列化器

在REST后台开发中,我们需要通过业务逻辑来选择数据集或者序列化器. 选择数据集: # 重写get_queryset实现通过业务逻辑选择指定数据集 def get_queryset(self): ''' 通过前段传递过来的keyword选择指定数据集 :return: ''' # 获取keyword keyword = self.request.query_params.get('keyword') # 通过前段传递过来的keyword选择指定数据集 if keyword: users = Us

【DRF序列化】

目录 基本的序列化操作 外键/多对多关系的序列化 反序列化的操作 单条数据查询及更新 数据的校验 单个字段的校验 多个字段的校验 自定义校验器 终极用法 ModelSerializer "前后端分离后,其交互一般都选择使用JSON数据格式,JSON是一个轻量级的数据交互格式. 因此,后端发送给前端(或前端发送给后端)的数据都要转成JSON格式,这就得需要我们把从数据库内取到的数据进行序列化. 本文将详细讲述Django项目中如何使用第三方库rest_framework进行序列化. 在命令行中输入