django ModelSerializer自定义显示字段

news2024/11/20 6:35:56

文章目录

  • 前言
  • 一、问题
  • 二、解决


前言

最近在复习django的时候,发现了一个有趣的问题,解决了之后特意记录下来,以供以后参考。

一、问题

相信大家使用django的时候,被其DRF的强大功能所折服,因为它能通过简单的代码就能帮助我们实现增删改查等最简单的操作。我的demo代码如下:
模型类代码,models.py

from django.db import models


class StudentInfo(models.Model):
    name = models.CharField(max_length=10, verbose_name='姓名')
    sex = models.CharField(max_length=1, verbose_name='性别')
    from_class = models.ForeignKey(ClassInfo, on_delete=models.CASCADE)

序列化器代码,serializers.py

from rest_framework import serializers
from demo import models


class StudentInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.StudentInfo
        fields ="__all__"

视图代码,views.py

from rest_framework.viewsets import ModelViewSet
from .models import StudentInfo
from .serializers import StudentInfoSerializer


class DemoView(ModelViewSet):
    queryset = StudentInfo.objects.all()
    serializer_class = StudentInfoSerializer

路由代码,urls.py

from rest_framework.routers import SimpleRouter, DefaultRouter
from .views import DemoView
urlpatterns = []

# demo_route = SimpleRouter()
demo_route = DefaultRouter()

demo_route.register("demo", DemoView, basename="demo")

urlpatterns += demo_route.urls

最后在项目的主路由里面添加路径即可(需要在settings.py里面注册app):

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("user/", include("user.urls")),
    path("", include("demo.urls"))
]

效果:
在这里插入图片描述
但是,这样会出现一个问题,就是无法控制序列化结果显示的字段。例如,在同一个项目中,可能会出现多个场景,一个场景只需要用户的name和sex字段,一个场景只需要用户的name字段,一个场景则需要用户的全部字段,按照以上方法就需要设置三个序列化器了,显然不符合实际应用。那么有没有办法可以兼顾便捷和灵活呢?

二、解决

解决方法很简单,重写序列化器的__init__()方法即可:
serializers.py

# 动态修改fileds字段
class StudentInfoSerializer(serializers.ModelSerializer):
    """
         此处的`fields`字段是用来替换上面Serializer内部Meta类中指定的`fields`属性值
        """

    def __init__(self, *args, **kwargs):
        # 在super执行之前
        # 将传递的`fields`中的字段从kwargs取出并剔除,避免其传递给基类ModelSerializer
        # 注意此处`fields`中在默认`self.fields`属性中不存在的字段将无法被序列化 也就是`fields`中的字段应该是`self.fields`的子集
        fields = kwargs.pop('fields', None)

        super(StudentInfoSerializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # 从默认`self.fields`属性中剔除非`fields`中指定的字段(两个集合相减,会提出多余的元素)
            allowed = set(fields)
            existing = set(self.fields.keys())
            for field_name in existing - allowed:
                self.fields.pop(field_name)

    class Meta:
        model = models.StudentInfo
        fields ="__all__"

以上代码的原理也很简单,首先获取传入的fields参数(即你想要的字段);然后使用序列化器原有的字段减去你想要的字段,就获取了多余的字段;最后,循环遍历多余的字段,将它们从原有的字段中一个一个剔除
为了更好的展示结果,我这里自定义了三个路径:
views.py

from django.shortcuts import render

# Create your views here.
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from .models import StudentInfo
from .serializers import StudentInfoSerializer


class DemoView(ModelViewSet):
    queryset = StudentInfo.objects.all()
    serializer_class = StudentInfoSerializer

    @action(url_path="all_fields", methods=["GET"], detail=False)
    def all_fields(self, request):
        user_data = StudentInfo.objects.all()
        serializer = StudentInfoSerializer(instance=user_data, many=True)

        return Response(serializer.data)

    @action(url_path="name_sex", methods=["GET"], detail=False)
    def name_sex(self, request):
        user_data = StudentInfo.objects.all()
        serializer = StudentInfoSerializer(instance=user_data, fields=("name", "sex"), many=True)

        return Response(serializer.data)

    @action(url_path="name_fromclass", methods=["GET"], detail=False)
    def name_fromclass(self, request):
        user_data = StudentInfo.objects.all()
        serializer = StudentInfoSerializer(instance=user_data, fields=("name", "from_class"), many=True)

        return Response(serializer.data)

效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看出,根据传入的fields的不同,返回不同的结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1232984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

生产环境_移动目标轨迹压缩应用和算法处理-Douglas-Peucker轨迹压缩算法

场景: 我目前设计到的场景是:即在地图应用中,对GPS轨迹数据进行压缩,减少数据传输和存储开销,因为轨迹点太频繁了,占用空间太大,运行节点太慢了,经过小组讨论需要上这个算法&#x…

Nosql的redis概述及基本操作

关系数据库与非关系型数据库概述 关系型数据库 关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,一般面向于记录。SQL语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型…

【Linux专题】退出bash后再运行jobs命令为什么不会显示后台任务

【Linux专题】firewalld 过滤出接口流量-CSDN博客文章浏览阅读214次。风和日丽,小微给你送福利~如果你是小微的老粉,这里有一份粉丝福利待领取...如果你是新粉关注到了小微,那恭喜你,你赚到了![欢迎关注微信公众号&…

技巧大揭秘!如何优雅地应对Redis读写超时问题

大家好,我是小米!今天我们要聊的话题是在Java中如何优雅地处理Redis读写超时问题。这可是个让人头疼的问题,但别担心,我会在这里和大家一起揭开它的神秘面纱,分享一些超实用的技巧和优雅的处理方法。 问题背景 在我们…

陶瓷行业废污水处理使用MES系统的作用

陶瓷行业属于高能耗、高污染行业,生产过程中消耗大量矿产资源和能源,产生的废气、废水、废渣、粉尘等对环境造成严重污染。在近年来,全社会环保意识增强,政府出台了一系列政策、措施加大节能、减排力度,整治行业污染。…

NX二次开发UF_CAM_ask_lower_limit_plane_usage 函数介绍

文章作者:里海 来源网站:里海NX二次开发3000例专栏 UF_CAM_ask_lower_limit_plane_usage Defined in: uf_cam_planes.h int UF_CAM_ask_lower_limit_plane_usage(tag_t object_tag, UF_PARAM_lwplane_usage_t * usage ) overview 概述 Query the usa…

Nginx解决跨域问题的一些想法

参考博客https://blog.csdn.net/agonie201218/article/details/112562252,https://blog.csdn.net/Zisson_no_error/article/details/119357629。都是写得非常很好的文章 重中之重:一定要长眼睛,带脑子 通过跨域访问的报错,看清楚…

H5生成二维码(HTML、CSS、QrCodeJs内含源码)

H5生成二维码 前言二维码实现过程页面实现关键点全部源码 前言 本文主要讲解如何通过原生HTML、CSS、Js中的qrcodejs二维码生成库,实现一个输入URL按下回车后输出URL。文章底部有全部源码,需要可以自取。 实现效果图: 上述实现效果为&#…

2023年11月中旬大模型新动向集锦

2023年11月中旬大模型新动向集锦 2023.11.21版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 1、谷歌生成式 AI 搜索生成体验(SGE)扩展到 120 多个新国家/地区 近日,Google 扩展了其由生成式人工智能驱…

无法打开 “XXXX“ ,因为Apple 无法检测其是否包含恶意软件

解决方案 设置 - > 隐私和安全性 这里会显示这个,点击仍要打开

高压放大器使用方法介绍

高压放大器是一种用于放大高压信号的电子设备,常用于科学研究、工业应用和医疗设备等领域。它可以将低电压信号放大到较高的电压水平,以满足特定应用的需求。 使用高压放大器需要注意以下几个方面: 1.了解设备规格:在使用高压放大…

Linux操作系统使用及C高级编程-D9D10Linux 服务搭建与使用

TFTP服务器 TFTP(Trivial File Transfer Protocol)即简单文件传输协议,是TCP/IP协议中一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69 1、使用客户服务器方式和使用UDP数据…

Vue项目Jenkins自动化部署

1. 需求描述 我们希望提交uat分支时,UAT项目能够自动发布,提交master分支时,无需自动发布,管理员手工发布 2. 效果展示 3. 采用技术 Jenkins + K8S + Docker + Nginx 4. 具体实现 4.1 编写default.conf 在Vue项目根目录新建default.conf文件,主要进行代理配置、首页…

yum 搭建仓库 http/ftp

目录 http ftp http 服务端 1. 下载 httpd 服务,记得将防火墙和安全终端全部关掉 2. 开启 httpd 服务 3. 临时挂载 客户端 1. 下载 httpd 服务,记得将防火墙和安全终端全部关掉 2. 开启 httpd 服务 3. 进入 /etc/yum.repos.d 4. 新建一个目录 mhy&…

代码随想录 11.21 || 单调栈 LeetCode 84.柱状图中最大的矩形

84.柱状图中最大的矩形 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1。求在柱状图中,能够勾勒出来的矩形的最大面积。和 42.接雨水 类似,在由数组组成的柱状图中,根据条件求解。 图…

本地/笔记本/纯 cpu 部署、使用类 gpt 大模型

文章目录 1. 安装 web UI1.1. 下载代码库1.2. 创建 conda 环境1.3. 安装 pytorch1.4. 安装 pip 库 2. 下载大模型3. 使用 web UI3.1. 运行 UI 界面3.2. 加载模型3.3. 进行对话 使用 web UI 大模型文件,即可在笔记本上部署、使用类 gpt 大模型。 1. 安装 web UI 1…

nvm 离线安装,并离线安装指定版本 node

1. 离线安装 nvm 通常通过网络安装nvm的时候会被墙,所以nvm安装就只能进行离线安装了。 我们可以在github上下载nvm的安装包,然后在本地安装,下载地址:点击直达 点进去的详情长这样: 将下载下来的文件放到服务器&…

jdk9.0.1下载、安装、配置

下载路径xIndex of java-local/jdk/9.0.111 安装 环境变量配置 新增变量:JAVA_HOME 值:安装路径 path中新增:%JAVA_HOME%\bin

LeetCode【76】最小覆盖子串

题目&#xff1a; 思路&#xff1a; https://segmentfault.com/a/1190000021815411 代码&#xff1a; public String minWindow(String s, String t) { Map<Character, Integer> map new HashMap<>();//遍历字符串 t&#xff0c;初始化每个字母的次数for (int…