二、Django REST Framework (DRF)序列化反序列化

news2024/11/24 9:39:24

参考: 

为什么要学DRF和什么是REST API | 大江狗的博客

上一章:

一、Django REST Framework (DRF)& RESTful 风格api_做测试的喵酱的博客-CSDN博客

一、DRF框架介绍 

1.1 介绍

Django REST Framework (DRF)这个神器我们可以快速开发出优秀而且规范的Web API来。Django REST framework 给Django提供了用于构建Web API 的强大而灵活的工具包, 包括:

  • 序列化器Serializer,可以高效的进行序列化与反序列化操作。
  • 认证:多种身份认证
  • 权限
  • 分页
  • 过滤
  • 限流
  • 可扩展,插件丰富
  • 提供了极为丰富的类视图、Mixin扩展类、ViewSet视图集。

1.2 安装与配置

1、安装

pip install djangorestframework

其他插件:(非必需)

pip install  markdown

2、注册应用

INSTALLED_APPS = [
        'rest_framework',
]

二、演示数据准备

1、创建子应用miaoschool,注册应用

2、创建2个模型类,班级模型类MiaoClass,学生信息模型类MiaoStudent

models.py

from django.db import models

# Create your models here.

class MiaoClass(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='id', help_text='id')
    classname = models.CharField(max_length=20, verbose_name='班级名称', help_text='班级名称')
    clasleader = models.CharField(max_length=10, verbose_name='班主任姓名', help_text='班主任姓名')
    classcode = models.IntegerField(unique=True, verbose_name='班级code', help_text='班级code')
    ifopens = models.BooleanField(default=True, verbose_name='是否开学', help_text='是否开学')
    classrate = models.IntegerField( verbose_name='班费', help_text='班费')

    class Meta:
        # i.db_table指定创建的数据表名称
        db_table = 'tb_class'
        # 为当前数据表,设置中午呢描述
        verbose_name = "班级表"
        verbose_name_plural = "班级表"

class MiaoStudent(models.Model):
    sname = models.CharField(max_length=20, verbose_name='学生姓名', help_text='学生姓名')
    sgender = models.BooleanField(verbose_name='性别', help_text='性别')
    sage = models.IntegerField(verbose_name='年龄', help_text='年龄')
    sid = models.IntegerField(unique=True, verbose_name='学号', help_text='学号')
    sscore = models.IntegerField( verbose_name='成绩', help_text='成绩')
    classid = models.ForeignKey('miaoschool.MiaoClass',on_delete=models.CASCADE,verbose_name='班级id', help_text='班级id')


    class Meta:
        # i.db_table指定创建的数据表名称
        db_table = 'tb_student'
        # 为当前数据表,设置中午呢描述
        verbose_name = "学生信息表"
        verbose_name_plural = "学生信息表"

插入数据:

-- ----------------------------
-- Records of tb_class
-- ----------------------------
BEGIN;
INSERT INTO `tb_class` (`id`, `classname`, `clasleader`, `classcode`, `ifopens`, `classrate`) VALUES (1, '一班', '王老师', 1001, 1, 200);
INSERT INTO `tb_class` (`id`, `classname`, `clasleader`, `classcode`, `ifopens`, `classrate`) VALUES (2, '二班', '欧阳老师', 1006, 1, 300);
INSERT INTO `tb_class` (`id`, `classname`, `clasleader`, `classcode`, `ifopens`, `classrate`) VALUES (3, '三班', '东风老师', 1007, 1, 400);
INSERT INTO `tb_class` (`id`, `classname`, `clasleader`, `classcode`, `ifopens`, `classrate`) VALUES (4, '四班', '白腊图老师', 1011, 1, 20);
INSERT INTO `tb_class` (`id`, `classname`, `clasleader`, `classcode`, `ifopens`, `classrate`) VALUES (5, '五班', '张三丰老师老师', 1021, 1, 150);
COMMIT;

 

-- ----------------------------
-- Records of tb_student
-- ----------------------------
BEGIN;
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (1, '阿珍', 1, 18, 101, 100, 1);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (2, '李珍', 1, 18, 104, 100, 1);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (3, '孙珍', 1, 18, 102, 100, 1);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (7, '李爱', 1, 18, 106, 100, 1);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (9, '张三', 0, 18, 2301, 20, 2);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (10, '李爱', 1, 18, 107, 100, 1);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (11, '张三', 0, 18, 2302, 20, 2);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (12, '李三', 1, 19, 2325, 30, 2);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (13, '张红', 0, 20, 2303, 40, 2);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (14, '张珍', 1, 16, 2304, 50, 3);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (15, '刘慧珍', 0, 17, 2305, 60, 3);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (16, '王莫涵', 1, 18, 2306, 70, 3);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (17, '张茜茜', 0, 20, 2307, 80, 4);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (18, '学姐', 1, 15, 2308, 90, 4);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (19, '张绍京', 0, 14, 2309, 100, 4);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (20, '董超', 1, 20, 2311, 20, 5);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (21, '吕布', 0, 21, 2321, 40, 5);
INSERT INTO `tb_student` (`id`, `sname`, `sgender`, `sage`, `sid`, `sscore`, `classid_id`) VALUES (22, '黄大仙', 1, 17, 2322, 60, 5);
COMMIT;

 

 

 

三、序列化器Serializer

3.1 序列化&反序列化

每种编程语言都有各自的数据类型, 将属于自己语言的数据类型或对象转换为可通过网络传输或可以存储到本地磁盘的数据格式(如:XML、JSON或特定格式的字节串)的过程称为序列化(seralization);反之则称为反序列化。

API开发的本质就是各种后端语言的自己的数据类型序列化为通用的可读可传输的数据格式,比如常见的JSON类型数据。

3.2 Python数据序列化

举个简单例子。Python自带json模块的dumps方法可以将python常用数据格式(比如列表或字典)转化为json格式,如下所示。你注意到了吗? 生成的json格式数据外面都加了单引号,这说明dict类型数据已经转化成了json字符串。

>>> import json
>>> json.dumps({"name":"John", "score": 112})
'{"name": "John", "score": 112}'

3.3 DRF中的序列化与反序列化

序列化: 将 查询集QuerySet (多个模型类的集合)与单个模型类的实例,转化为 json数据(字符串)。

反序列化:将json格式的字符串数据,转换为Django中的模型类的对象。

3.4 DRF框架中实现序列化

1、在应用中,创建一个名为 serializers.py 的文件。(推荐命名为serializers.py,其他命名也可以)

3.4.1 定义序列化器类

1、定义序列化器类,必须得继承Serializer类或者Serializer子类

from rest_framework import serializers
class StudentSerializer(serializers.Serializer):

2、定义的序列化器类中,字段名要与模型类中的字段名保持一致。(字段个数可以不一致,但是字段名称一定要保持一致)
3、定义的序列化器类的字段(类属性)为Field子类

4、序列化器类中,定义了哪些字段,在序列化与反序列化中,只处理这些定义的字段,其他字段不处理。

 5.常用的序列化器字段类型。

跟模型类差不多

数据类型Field类型
intIntegerField
strCharField
boolBooleanField
datetimeDateTimeField

6、序列化器字段中常用的选项

a、  label和help_text,与模型类中的verbose_name和help_text参数一样

b、(用于数据校验) IntegerField,可以使用max_value指定最大值,min_value指定最小值

c、 (用于数据校验)CharField,可以使用max_length指定最大长度,min_length指定最小长度
     

 3.4.2 序列化器字段中常用的选项(数据校验)

a、  label和help_text,与模型类中的verbose_name和help_text参数一样

b、(用于数据校验) IntegerField,可以使用max_value指定最大值,min_value指定最小值

c、 (用于数据校验)CharField,可以使用max_length指定最大长度,min_length指定最小长度
     

四、序列化

4.1 应用场景:

用户请求数据,从数据库取出数据,反给用户。ORM框架,从数据库中取的数据是QuerySet。

通过序列化将QuerySet 转化为josn数据返回给用户。

4.2 创建序列化器类

序列化器类,字段与模型类字段基本一致,用来做将模型类实例与json数据相互转换的中间件。

serializers.py 

# -*- coding:utf-8 -*-
# @Author: 喵酱
# @time: 2023 - 05 -21
# @File: serializers.py
# desc: 序列化器
from rest_framework import serializers

class StudentSerializer(serializers.Serializer):

    id = serializers.IntegerField(label='学生id', help_text='学生id', max_value=1000, min_value=1)
    sname = serializers.CharField(label='学生姓名', help_text='学生姓名',max_length=10,min_length=1 )
    sgender =serializers.BooleanField(label='学生性别', help_text='学生性别',)
    sage = serializers.IntegerField(label='学生年龄', help_text='学生年龄',max_value=100, min_value=1)
    sid = serializers.IntegerField(label='学生学号', help_text='学生学号',)
    sscore = serializers.IntegerField(label='学生成绩', help_text='学生成绩', max_value=100, min_value=0)
    # 注意,转换外键的值时,输入使用类属性名称来转化,接收到的是一个主表的实例对象
    classid = serializers.CharField(label='班级id', help_text='班级id',)
    # 注意,转换外键的值时,输入使用从表中外键的值来转化,接收到的是一个真正的数值
    classid_id = serializers.IntegerField(label='班级id', help_text='班级id', max_value=10, min_value=1)

 注意外键的处理:

    # 注意,转换外键的值时,输入使用类属性名称来转化,接收到的是一个主表的实例对象
    classid = serializers.CharField(label='班级id', help_text='班级id',)
    # 注意,转换外键的值时,输入使用从表中外键的值来转化,接收到的是一个真正的数值
    classid_id = serializers.IntegerField(label='班级id', help_text='班级id', max_value=10, min_value=1)

4.3 读取多条数据,处理Queryset

一、视图函数的处理。

def get_student_all(request):
    queryset=MiaoStudent.objects.all()
    print(queryset)
    serializer = StudentSerializer(instance=queryset, many=True)
    return JsonResponse(serializer.data, safe=False)

注意:

1、 QuerySet 是多个模型类实例的集合。返回给用户的数据格式不是json,而是一个列表,每个元素是一个json。

2、处理QuerySet,一定要使用many=True

serializer = StudentSerializer(instance=queryset, many=True)

3、将序列化对象实例,转化为json的列表。

serializer.data 是序列化后的数据

JsonResponse(serializer.data, safe=False)

二、请求返回数据

[
    {
        "id": 1,
        "sname": "阿珍",
        "sgender": true,
        "sage": 18,
        "sid": 101,
        "sscore": 100,
        "classid": "MiaoClass object (1)",
        "classid_id": 1
    },
    {
        "id": 2,
        "sname": "李珍",
        "sgender": true,
        "sage": 18,
        "sid": 104,
        "sscore": 100,
        "classid": "MiaoClass object (1)",
        "classid_id": 1
    },
    {
        "id": 3,
        "sname": "孙珍",
        "sgender": true,
        "sage": 18,
        "sid": 102,
        "sscore": 100,
        "classid": "MiaoClass object (1)",
        "classid_id": 1
    },
    {
        "id": 7,
        "sname": "李爱",
        "sgender": true,
        "sage": 18,
        "sid": 106,
        "sscore": 100,
        "classid": "MiaoClass object (1)",
        "classid_id": 1
    },
    {
        "id": 9,
        "sname": "张三",
        "sgender": false,
        "sage": 18,
        "sid": 2301,
        "sscore": 20,
        "classid": "MiaoClass object (2)",
        "classid_id": 2
    },
    {
        "id": 10,
        "sname": "李爱",
        "sgender": true,
        "sage": 18,
        "sid": 107,
        "sscore": 100,
        "classid": "MiaoClass object (1)",
        "classid_id": 1
    },
    {
        "id": 11,
        "sname": "张三",
        "sgender": false,
        "sage": 18,
        "sid": 2302,
        "sscore": 20,
        "classid": "MiaoClass object (2)",
        "classid_id": 2
    },
    {
        "id": 12,
        "sname": "李三",
        "sgender": true,
        "sage": 19,
        "sid": 2325,
        "sscore": 30,
        "classid": "MiaoClass object (2)",
        "classid_id": 2
    },
    {
        "id": 13,
        "sname": "张红",
        "sgender": false,
        "sage": 20,
        "sid": 2303,
        "sscore": 40,
        "classid": "MiaoClass object (2)",
        "classid_id": 2
    },
    {
        "id": 14,
        "sname": "张珍",
        "sgender": true,
        "sage": 16,
        "sid": 2304,
        "sscore": 50,
        "classid": "MiaoClass object (3)",
        "classid_id": 3
    },
    {
        "id": 15,
        "sname": "刘慧珍",
        "sgender": false,
        "sage": 17,
        "sid": 2305,
        "sscore": 60,
        "classid": "MiaoClass object (3)",
        "classid_id": 3
    },
    {
        "id": 16,
        "sname": "王莫涵",
        "sgender": true,
        "sage": 18,
        "sid": 2306,
        "sscore": 70,
        "classid": "MiaoClass object (3)",
        "classid_id": 3
    },
    {
        "id": 17,
        "sname": "张茜茜",
        "sgender": false,
        "sage": 20,
        "sid": 2307,
        "sscore": 80,
        "classid": "MiaoClass object (4)",
        "classid_id": 4
    },
    {
        "id": 18,
        "sname": "学姐",
        "sgender": true,
        "sage": 15,
        "sid": 2308,
        "sscore": 90,
        "classid": "MiaoClass object (4)",
        "classid_id": 4
    },
    {
        "id": 19,
        "sname": "张绍京",
        "sgender": false,
        "sage": 14,
        "sid": 2309,
        "sscore": 100,
        "classid": "MiaoClass object (4)",
        "classid_id": 4
    },
    {
        "id": 20,
        "sname": "董超",
        "sgender": true,
        "sage": 20,
        "sid": 2311,
        "sscore": 20,
        "classid": "MiaoClass object (5)",
        "classid_id": 5
    },
    {
        "id": 21,
        "sname": "吕布",
        "sgender": false,
        "sage": 21,
        "sid": 2321,
        "sscore": 40,
        "classid": "MiaoClass object (5)",
        "classid_id": 5
    },
    {
        "id": 22,
        "sname": "黄大仙",
        "sgender": true,
        "sage": 17,
        "sid": 2322,
        "sscore": 60,
        "classid": "MiaoClass object (5)",
        "classid_id": 5
    }
]

 4.4 读取单条数据,处理模型类的实例

一、视图函数的处理。

def get_student_one(request):
    obj=MiaoStudent.objects.get(id=10)
    serializer = StudentSerializer(instance=obj)
    return JsonResponse(serializer.data)

注意:

obj 是一个模型类的实例。

将模型类的实例,序列化

serializer = StudentSerializer(instance=ojb)

 serializer.data 是序列化后的数据

将序列化对象实例,转化为json的数据。

JsonResponse(serializer.data, safe=False)

五、反序列化

5.1 应用场景:

用户传入json请求数据,先将用户传入的json 字符串,转为字典,再将这个字典反序列化转化为模型类的实例,然后再调用ORM框架,执行sql。

比如创建学生信息,用户输入一个json,然后将这个json生成一行表的数据。

5.2 数据处理

1、获取接口请求json参数,并转化为字典。

我们手动对输入数据做一次简单的校验,是否能转成字典

def get_json(request):
    try:
        # 1、获取接口请求json参数,并转化为字典
        data = json.loads(request.body)
    except Exception as e:
        return JsonResponse({"msg":"参数有误"},status=400)

5.3 数据校验

序列化器提供了数据校验功能。

定义序列化器类,使用data关键字参数传递字典参数。

1、序列化器类:

在创建序列化器类时,如

sscore = serializers.IntegerField(label='学生成绩', help_text='学生成绩', max_value=100, min_value=0)

指定了sscore字段的校验规则,大于等于0,小于等于100。

sname = serializers.CharField(label='学生姓名', help_text='学生姓名',max_length=10,min_length=1 )

指定了sname字段的校验规则,最少1个字符,最多10个字符。

2、调用校验功能:

序列化器对象调用.is_valid()方法,才会开始对前端输入的参数进行校验

# 获取反序列化的实例对象
student_obj=StudentSerializer(data=data)

调用校验方法

student_obj.is_valid()

返回值为布尔类型,校验通过为True,校验失败为False。

3、获取校验失败的报错信息:

.只有在调用.is_valid()方法之后,才可以使用序列化器对象调用.errors属性,来获取错误提示信息(字典类型)

只有在调用

student_obj.is_valid()

校验之后,才可以查看报错信息,不然报错。

查看报错信息

student_obj.errors

4、在校验不通过时,直接抛出异常。

调用.is_valid()方法,添加raise_exeception=True,校验不通过会抛出异常。

student_obj.is_valid(raise_exeception=True)

5、校验之后的数据.validated_data

student_obj.validated_data

只有在调用.is_valid()方法之后,才可以使用序列化器对象调用.validated_data属性,来获取校验通过之后的数据。

.validated_data 数据与 使用json.load转化之后的数据有区别

6、整体代码:

def post_json(request):
    try:
        # 1、获取接口请求json参数,并转化为字典
        data = json.loads(request.body)
    except Exception as e:
        return JsonResponse({"msg":"参数有误"},status=400)

    # 获取反序列化的实例对象
    student_obj=StudentSerializer(data=data)
    # 对数据进行校验
    # 校验不通过
    if not student_obj.is_valid():
        return JsonResponse(student_obj.errors,status=400)
    # 创建数据,执行saql
    MiaoStudent.objects.create(**student_obj.validated_data)
    return JsonResponse({"msg":"创建成功"})

7、功能演示

a、传入sscore大于100的数字

http://127.0.0.1:8000/post_json/

参数:

{
    "sname":"浩轩",
    "sgender":1,
    "sage":17,
    "sid":2046,
    "sscore":101,
    "id":26,
    "classid_id":3

}

返回结果:

{
    "sscore": [
        "Ensure this value is less than or equal to 100."
    ]
}

b、传入ssname长度为11位字符

传参:

{
    "sname":"浩哈哈哈哈哈哈哈哈哈哈哈哈哈哈轩",
    "sgender":1,
    "sage":17,
    "sid":2046,
    "sscore":101,
    "id":26,
    "classid_id":3

}

返回结果:

{
    "sname": [
        "Ensure this field has no more than 10 characters."
    ],
    "sscore": [
        "Ensure this value is less than or equal to 100."
    ]
}

疑问:

为啥我的提示是英文?明天查查。

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

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

相关文章

基于SpringBoot的网吧管理系统的设计与实现

背景 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代&a…

ICR-预测三种医学状况 #$60,000 #Kaggle

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…)比赛。本账号会推送最新的比赛消息,欢迎关注! 以下信息由AI辅助创作,仅供参考 比赛名称 ICR - Identifying Age-Related Conditions[2] (见文末阅读原…

chatgpt赋能Python-pythonforrange

Python中的Range函数 在Python编程语言中,range()是一个用于生成一系列数字的函数。它可以接受1至3个整型参数:起始值、终止值和步长。生成的数字包括起始值,但不包括终止值。步长默认为1。 Range函数的语法 Python中range()函数的常规语法…

C++视角下的Qt按钮:从基础应用到高级定制

C视角下的Qt按钮:从基础应用到高级定制 一、Qt按钮基础 (Qt Button Basics)1.1 Qt按钮的定义与创建 (Definition and Creation of Qt Buttons)1.2 Qt按钮的属性 (Properties of Qt Buttons)文本 (Text)图标 (Icon)大小 (Size)样式 (Style)是否可用 (Enabled) 1.3 Qt…

Java【TCP 协议3】提高效率的五大机制

文章目录 前言一、滑动窗口与高速重传1, 什么是滑动窗口2, 什么是高速重传2.1, ack 丢包2.2, 数据丢包 二、流量控制1, 什么是流量控制 三、拥塞控制1, 什么是拥塞控制 四、延迟应答1, 什么是延迟应答 五、捎带应答1, 什么是捎带应答 总结 前言 各位读者好, 我是小陈, 这是我的…

JavaScript实现1-100之间所有的素数的代码

以下为实现1-100之间所有的素数的程序代码和运行截图 目录 前言 一、1-100之间所有的素数 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有选择,您可以在目录里进行快速查找; 2.本博文代码可以根据题目要求实现…

防火墙(二)

进一步了解防火墙 一、SNAT原理与应用模拟实验 二、DNAT的原理与应用模拟实验 三、抓包四、防火墙规则的备份和还原 一、SNAT原理与应用 SNAT应用环境:局域网主机共享单个公网IP地址接入Internet(私有不能早Internet中正常路由) SNAT原理&am…

【2023 · CANN训练营第一季】新手班 昇腾AI入门课(PyTorch)

1 昇腾AI全栈架构 昇腾计算产业是基于昇腾系列处理器和基础软件构睫的全栈Al计算基础设施.行业应用及服务,包括昇腾系列处理器、Atlas系列硬件、CANN (Compute Architecture for Neural Networks,异构计算架构》、Al计算框架、应用使能、全流…

nRF52832 定时器REPEATED模式,导致异常重启的问题排查全过程

文章目录 一、遇到问题二、JLink连接时,无法复现三、查看日志四、回退改动五、解决问题六、问题剖析 一、遇到问题 nRF52832项目增加一个功能,自测没问题就发出去了。结果300台机器,有7台出现异常,无法正常使用。细看了一遍提价上…

论文阅读_音频生成_AudioLM

论文信息 name_en: AudioLM: a Language Modeling Approach to Audio Generation name_ch: AudioLM:一种音频生成的语言建模方法 paper_addr: http://arxiv.org/abs/2209.03143 doi: https://doi.org/10.48550/arXiv.2209.03143 date_read: 2023-04-25 date_publis…

打开数据结构大门——实现小小顺序表

文章目录 前言顺序表的概念及分类搭建项目(Seqlist):apple:搭建一个顺序表结构&&定义所需头文件&&函数:banana:初始化:pear:打印:watermelon:数据个数:smile:检查容量:fireworks:判空:tea:在尾部插入数据:tomato:在尾部删除数据:lemon:在…

封装Appium启动参数,提高自动化测试效率的关键

目录 前言: 一、开发环境搭建 二、代码实现 1.导入Appium相关的库文件。 2.创建Appium的启动参数对象,并设置相关参数。 3.启动测试服务。 4.执行测试用例。 5.结束测试服务。 三、总结 前言: Appium是一款广泛使用的自动化测试工具…

Microsoft Office 2007的安装

哈喽,大家好。今天一起学习的是office2007的安装,有兴趣的小伙伴也可以来一起试试手。 一、测试演示参数 演示操作系统:Windows 7 不建议win10及以上操作系统使用 系统类型:64位 演示版本:cn_office_ultimate_2007_D…

从 SIEM 到下一代 SIEM 的演变

在此文中,我们详细介绍了下一代 SIEM 的演变。传统的 SIEM 主要用于提高网络可见性和网络安全性,同时支持合规性。它们跨应用程序、网络和系统摄取、收集和存储日志数据。 SIEM 使捕获和搜索数据变得更加容易,这些数据有助于组织进行审计、取…

详解RGB和XYZ色彩空间转换之下

前言 首先需要指明本文中描述的R,G,B并非通常的sRGB中的三个分量R,G,B,而是波长分别为700nm,546.1nm,435.8nm的单色红光,单色绿光,单色蓝光。sRGB中的RGB中的红色、绿色、蓝色已经不是单色光了。虽然习惯上大家都叫RGB…

Docker数据目录迁移方法

文章目录 前言一、停掉Docker服务?二、迁移docker数据到数据盘目三、备份原数据目录四、添加软链接五、重启docker服务六、确认服务没有问题后,删除备份的目录总结 前言 服务器上安装的docker服务,数据默认存储在/var/lib/docker目录&#x…

html5网页播放器视频切换、倍速切换、视频预览的代码实例

本文将对视频播放相关的功能进行说明,包括初始化播放器、播放器尺寸设置、视频切换、倍速切换、视频预览、自定义视频播放的开始/结束时间、禁止拖拽进度、播放器皮肤、控件按钮以及播放控制等。 图 / html5视频播放器调用效果(倍速切换) 初始…

网络知识点之-动态路由

动态路由是指路由器能够自动地建立自己的路由表,并且能够根据实际情况的变化适时地进行调整。 中文名:动态路由外文名:dynamic routing 简述 动态路由是与静态路由相对的一个概念,指路由器能够根据路由器之间的交换的特定路由信息…

usb摄像头驱动-core层USB集线器(Hub)驱动

usb摄像头驱动-core层USB集线器(Hub)驱动 文章目录 usb摄像头驱动-core层USB集线器(Hub)驱动usb_hub_inithub_probehub_eventport_eventhub_port_connect_changehub_port_connectusb_new_deviceannounce_device 在USB摄像头驱动中…

20.04Ubuntu换源:提升软件下载速度和更新效率

在使用Ubuntu操作系统时,一个常见的优化措施是更改软件源,以提高软件下载速度和更新效率。软件源是指存储软件包的服务器,通过更换软件源,你可以选择更靠近你所在地区的服务器,从而加快软件下载速度,并减少…