DRF学习之DRF初识

一.Web应用两种开发模式

1、前后端不分离模式

也叫前后端混合开发模式, 需要后端写模板语言(DTL), 返回的是HTML页面,比如有BBS项目,图书管理系统。

在前后端不分离的项目中,模板渲染通常是在后端完成的。这种项目结构中,后端负责处理业务逻辑、与数据库交互,并最终生成 HTML 页面,将数据填充到模板中,然后将完整的 HTML 页面发送给浏览器进行渲染。
在这里插入图片描述

2、前后端不分离

从程序角度来看:

  • 1个Django程序,接收请求+处理+HTML模版+用户返回
  • 2个程序:
    • 前端:vue.js/react.js/angular.js
    • 后端:Django + DjangoRestFramework

从专业度角度来看:

  • 前端,专门写前端代码 + 部署 + 版本管理 + ajax请求获取
  • 后端,API接口文档,只专注于写后端接口, 返回 json, xml格式数据

在前后端分离的项目中,模板渲染通常是在前端完成。在这种项目结构下,后端主要负责提供数据接口(通常是 JSON 格式),而前端则负责将这些数据获取并渲染到页面上。

在这里插入图片描述

二、什么是drf?作用是什么

1、简介

**DRF ( Django REST framework)**是一个用于构建 Web API 的强大且灵活的工具包,基于 Django Web 框架。DRF 提供了一组用于快速开发 Web API 的工具和功能,使得构建 RESTful API 变得简单和高效。也使后端开发人员更方便的编写API接口。

DRF 的设计理念是使构建 Web API 变得简单、快速且易于维护。它与 Django 框架紧密集成,为开发者提供了丰富的功能和工具,使得构建强大的 RESTful API 成为可能。

2、作用

  1. 构建 RESTful API:DRF 提供了丰富的工具和功能,使开发者能够轻松地构建符合 REST 架构风格的 Web API。通过使用 DRF,开发者可以快速地创建支持标准 HTTP 方法(如 GET、POST、PUT、DELETE 等)的 API。

  2. 序列化和反序列化:DRF 提供了序列化器(Serializers),用于处理数据的序列化和反序列化操作。这使得在 API 请求和响应中处理复杂的数据结构变得更加简单和高效。

  3. 认证和权限控制:DRF 提供了灵活的认证和权限控制系统,开发者可以轻松地实现基于 token、session、OAuth 等各种认证方式,并定义细粒度的权限控制规则。

  4. 视图类:DRF 提供了多种视图类,包括基于类的视图(Class-based Views)和函数视图(Function-based Views),以及通用视图类(Generic Views),帮助开发者快速构建 API 视图。

  5. 路由:DRF 提供了简单而强大的路由系统,可以方便地映射 URL 到视图函数或类,从而定义 API 的端点。

  6. 文档生成:DRF 集成了强大的 API 文档生成工具,可以自动生成交互式的 API 文档,帮助开发者和用户了解 API 的结构、参数和用法。

三、API接口

1、什么是API接口?

API(Application Programming Interface)接口是一组定义和描述不同软件系统之间如何互相通信的规则集合。在软件开发中,API 接口允许不同的应用程序之间共享数据和功能,从而实现更高层次的集成和互操作性。

API 接口可以是不同形式的,其中最常见的是 Web API,它通过网络(通常是通过 HTTP 协议)暴露服务,并允许其他应用程序通过发送请求和接收响应的方式与之交互。

通俗一点来说,web后端提供给前端可以调用的访问拿到数据的东西接口可以称之为API接口。API接口是前后端交互的媒介。

2、API接口应该有哪些东西?

Web API接口和一般的url链接还是有区别的,Web API接口简单概括有下面四大特点:

  • url地址:长得像返回数据的url链接
    • https://api.map.baidu.com/place/v2/search
  • 请求方式:get、post、put、patch、delete
    • 采用get方式请求上方接口
  • 请求参数:Json格式或者XML格式的key-value类型数据
    • GET请求数据:地址栏中的数据----->request.GET
    • 请求体中数据:reqeust.POST’
      • 早些年 前后端交互使用XML格式,ajax其实就是异步JavaScript和XML
      • 后来 随着Json格式的出现,乃至今日都是主流
      • 未来 可能会有更高效、安全的交互格式会替代目前的Json格式
  • 响应结果:Json格式或者XML格式的数据

3、补充 Json格式与XML格式的区别

JSON(JavaScript Object Notation)和 XML(eXtensible Markup Language)都是用于在不同系统之间交换数据的常见格式,它们有以下几点区别:

  1. 语法

    • JSON:JSON 是一种轻量级的数据交换格式,采用键值对的方式表示数据。数据以键值对的形式存储,使用大括号 {} 表示对象,使用方括号 [] 表示数组。
    • XML:XML 是一种标记语言,使用标签(tag)来描述数据结构。XML 使用尖括号 <> 包围标签,标签可以嵌套表示复杂的数据结构。
  2. 可读性

    • JSON:JSON 的语法相对简洁,易于阅读和编写。对于人类来说更易于理解。
    • XML:XML 的语法相对繁琐,标签较多,使得文件相对冗长。但由于标签的结构清晰,有时也更易于理解复杂的数据结构。
  3. 数据体积

    • JSON:由于 JSON 的语法相对简洁,通常比 XML 更紧凑,数据体积更小,传输效率更高。
    • XML:XML 的冗长标签和结构使得数据文件相对较大,传输效率相对较低。
  4. 数据类型

    • JSON:JSON 支持基本数据类型(字符串、数字、布尔值、数组、对象)以及 null 值。对于简单的数据结构和前后端交互,JSON 更为常用。
    • XML:XML 可以描述更复杂的数据结构,并支持自定义数据类型和命名空间。在某些情况下,如配置文件或复杂的数据交换,XML 可能更适用。
  5. 解析和处理

    • JSON:JSON 的解析速度比 XML 更快,因为 JSON 的结构更简单。
    • XML:XML 的解析相对复杂,需要更多的处理步骤,解析速度比 JSON 慢。

总的来说,JSON 更适用于简单数据结构和前后端交互,而 XML 更适用于描述复杂数据结构和传输带有元数据的文档。在实际应用中,可以根据具体需求选择合适的格式。

四、API接口测试工具:Postman

1、安装

  • Postman下载安装教程-CSDN博客

2、使用

在这里插入图片描述
在这里插入图片描述

**① 😗*可以切换请求方法:post,put,get等

**② params:参数:**设置一些请求的参数的地方,通常适用于一些get的没有请求体的请求

**③ authorization:**鉴权:有些请求需要验证身份,采取不同的鉴权方式,携带内容,验证你的身份(和token的作用类似)

④ headers:请求头:携带请求的一些必要信息例如:Content-Type和token等

在这里插入图片描述

**⑤ body:**请求体:

  • none:没有请求体

  • form-data:表单格式的内容,即可上传键值对,又可以上传文件,选择不同的内容请求头的Content-Type对应值不同 x-www-form-urlencoded:只可以上传键值对

  • raw:原始数据(有text,javascript,json,html,xml)等不同格式的数据,按接口要求上传数据 选择text,则请求头是: text/plain

  • 选择javascript,则请求头是: application/javascript

  • 选择json,则请求头是: application/json (如果想以json格式传参,就用raw+json就行了)

  • 选择html,则请求头是: text/html

  • 选择application/xml,则请求头是: application/xml

  • binary:相当于Content-Type:application/octet-stream,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以,一次只能上传一个文件

  • GraphQL:数据类型对参数具体的类型会有一定的标准

  • Cookies:验证身份的一种方式

⑥ Pre-request Script:预请求脚本也叫做前置脚本,在请求发生之前先发生的脚本,请求中需要用的一些内容,可太勇敢前置脚本获得

⑦ tests:后置脚本,请求之后发生的一些脚本,此接口的响应有一些其他接口用的内容,可通过tests传递出去

可以设置获取变量也可以设置断言方法

⑧ settings:设置:设置这个请求需要的一些条件,比如证书,请求头设置,等,根据需要设置

在这里插入图片描述

  • body:响应体
    • Pretty:响应展示的视图格式化显示:JSON,XML,HTML,Text,Auto这几种类型的响应

    • Raw:响应的原始文本,未格式化的

    • Preview:视图:一些html的响应方便查看

    • Visualize:可视化:一些图片验证码的响应就可以在此处查看

  • cookies:当响应中有cookies时会在这里显示
  • headers:响应头:展示响应头的信息
  • test results:测试结果:当在请求中有断言的时候,测试的结果会在此处展示

3、补充 body的编码格式

  • get 请求,可以在地址栏中带数据—》能不能在body体中带数据—》能!
    • -注意:可以提交到后端,但是django框架没有放在request.POST中,放在request.body中
  • urlencoded 编码格式—》请求体中–》name=%E5%BD%AD%E4%BA%8E%E6%99%8F&age=38
  • form-data格式:携带文件和数据
    • 文件:request.FILES.get(‘myfile’)
    • 数据:request.POST.get()
    • request.body 能不能用,取决于文件大小,一般不用打印body(会报错)
      • 因为http是基于tcp的协议,而tcp是流式协议,一次性发达文件会报错
  • json格式
    • request.POST 是没有数据的
    • request.body 中有 —> 需要自己在后端转成自己需要的格式数据

4、postman创建文件,导入和导出

  • 这些操作需要我们先登录才能操作,所以记得注册一个账号,反正免费

在这里插入图片描述

在这里插入图片描述

  • 创建完请求之后一定要记得保存

五、RESTful API规范

RESTful API 是一种基于 REST 架构风格设计的 API,它遵循一组约定和规范,以提供统一的接口,使得不同系统之间能够更轻松地进行通信和交互。以下是设计 RESTful API 时应遵循的一些规范:

1、数据的安全保障

  • url链接一般都采用https协议进行传输
  • 注:采用https协议,可以提高数据交互过程中的安全性

2、url地址中带接口标识

  • https://api.baidu.com
  • https://www.baidu.com/api/

3、url中带版本标识

  • 接口有版本
    • https://api.baidu.com/v1/login
    • https://api.baidu.com/v2/login

4、数据即是资源,均使用名词(可复数)

  • 以后所有接口路径中,尽量不出现动词
  • 接口一般都是完成前后台数据的交互,交互的数据我们称之为资源
    • https://api.baidu.com/v1/users
    • https://api.baidu.com/v1/books
    • https://api.baidu.com/v1/books/3

5、请求方式决定如何操作资源【增,删,改,查:curd】

  • https://api.baidu.com/books - get请求:获取所有书

  • https://api.baidu.com/books/1 - get请求:获取主键为1的书

  • https://api.baidu.com/books - post请求:新增一本书

  • https://api.baidu.com/books/1 - put请求:整体修改主键为1的书

  • https://api.baidu.com/books/1 - delete请求:删除主键为1的书

6、url中带搜索条件

  • 当我们发送请求需要对应参数时直接在对应请求url后携带即可。只针对于查询所有

  • https://api.baidu.com/v1/user?username=bbs123&user_id=1

7、响应中带状态码

  • http响应状态码
    • 1xx :请求正在处理 --> 客户端看不到
    • 2xx :正常响应—> 经常看到的有
      • 200:请求成功
      • 201:创建成功
    • 3xx :重定向—》偶尔看到 301 和 302
    • 4xx :客户端异常—》403: 404
    • 5xx: 服务端错误 500
  • 有趣的状态码记忆方法:
    • https://www.sohu.com/a/278045231_120014184
  • 自定制状态码
    • 例如:mysql–> 连接连不上–> 有个错误提示信息:错误码,错误描述
    • 我们也可以自己定制,但是一定要把错误提示码对应的错误消息公布出来让别人知道

8、响应中带信息描述(错误,正常)

  • 例如:code,message
  • { code: 1000, message: 成功}

9、针对不同操作符合以下规范

  • 统一规范的错误响应格式,包括错误码、错误信息和可能的解决方案。客户端可以根据错误信息快速定位问题所在。

  • 比如:

  • GET /collection:返回资源对象的列表(数组)

    • {code:100,msg:成功,results:[{},{},{}]}
  • GET /collection/resource:返回单个资源对象 {}

    • {code:100,msg:成功,result:{}}
  • POST /collection:返回新生成的资源对象 {}

  • PUT /collection/resource:返回完整的资源对象 {}

  • DELETE /collection/resource:返回一个空文档

    • {code:100,msg:删除成功}

10、返回数据中带链接

RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

比如,当用户向api.example.com的根目录发出请求,会得到这样一个文档。

{"link": {"rel":   "collection https://www.example.com/zoos","href":  "https://api.example.com/zoos","title": "List of zoos","type":  "application/vnd.yourformat+json"
}}

上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。

Hypermedia API的设计被称为HATEOAS。Github的API就是这种设计,访问api.github.com会得到一个所有可用API的网址列表。

六、序列化与反序列化

api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把数据转换格式,序列化可以分两个阶段:【序列化值的是转换数据格式:序列化,反序列化】

1、序列化

序列化: 把我们识别的数据转换成指定的格式提供给别人

站在python后端来看:把python的对象【字典,列表,对象】—> 转成json/xml格式字符串过程称之为序列化。

从数据库取出来—> 给前端 也可以叫序列化

例如:我们在django中获取到的数据默认是模型对象(qs/单个对象),但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。

2、反序列化

反序列化:把别人提供的数据转换/还原成我们需要的格式。

前端给我们的数据----> 我们保存到数据库中 也可以叫反序列化

例如:前端js提供过来的json/xml数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中

3、js中的序列化和反序列化

js 如何把对象序列化成字符串:【JSON.stringify()】,把字符串反序列化成对象:【JSON.parse()】

4、小结

  • 序列化:
    • drf称为 read(读取数据)
    • queryset — > json
    • 返给前端
  • 反序列化:
    • drf称为 write(写入数据)
    • 字符串 — > json
    • 接收前端的数据

七、初步编写API

1、基于drf实现

(1)安装

pip install djangorestframework

(2)注册

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config','rest_framework'
]

(3)返回数据界面

返回的是数据 + 嵌套好看的页面

路由

path('login/',views.login)
path('info/',views.InfoView.as_view())

视图

  • FBV
from rest_framework.response import Response
from rest_framework.decorators import api_view@api_view(["GET"])
def login(request):return Response({'status':True,'message':"success"})
  • CBV
from rest_framework.response import Response
from rest_framework.views import APIView
class InfoView(APIView):def get(self,request):Response({'status': True, 'message': "success"})

八、DRF快速使用

1、安装DRF

  • 使用pip包管理器,在终端中运行以下命令来安装DRF
pip install djangorestframework
  • 最新的drf,必须django 3.x以上,配置MySQL3.8版本以上

2、注册

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config','rest_framework'
]

3、创建表

import uuid
from django.db import modelsclass Task(models.Model):task_id = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)task_name = models.CharField(max_length=255, db_index=True)task_time = models.DateTimeField(auto_now_add=True)task_desc = models.TextField()

4、创建序列化器(Serializer):

  • 序列化器是DRF中一个重要的概念,它将Python对象转换为JSON等可被传输的格式,并可以反序列化接收到的数据。
  • 在你的应用程序中创建一个名为serializers.py的文件,并定义你的序列化器类。
  • 一个示例:
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):class Meta:model = Taskfields = '__all__'
  • 在这个示例中,我们使用ModelSerializer来自动创建序列化器类。

5、创建视图(View)

  • 在你的应用程序中创建一个名为views.py的文件,并定义视图类。
  • 一个示例:
from .models import Task
from .serializer import TaskSerializer
from rest_framework.viewsets import ModelViewSet
class TaskView(ModelViewSet):queryset = Task.objects.all()serializer_class = TaskSerializer

6、配置URL路由

  • 在你的应用程序的urls.py文件中,定义DRF的URL路由。
  • 一个示例:
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('task', TaskView, 'task')
urlpatterns = [
]
urlpatterns += router.urls
  • 通过上述配置,当访问127.0.0.1:8000/task/时,将会调用TaskView视图。

7、测试代码

import requests# res = requests.get('http://127.0.0.1:8000/app01/task/')
# print(res.text)
from threading import Thread# 多线程新增数据
def task(task_id, task_name):data = {"task_id": task_id,"task_name": task_name,"task_time": "2024-04-10 11:54:56","task_desc": "很重要,不能忘记"}res = requests.post('http://127.0.0.1:8000/app01/task/', json=data)print(res.text)if __name__ == '__main__':l = []for i in range(30):t = Thread(target=task, args=['asdfads-33-as-%s' % i, '任务00%s' % i])t.start()l.append(t)for i in l:i.join()

九、CBV源码剖析

(1)cbv写法:

  • 视图中写视图类,继承View,写跟请求方式同名的方法
class TaskView(View):def get(self,request):return 四件套
  • 在路径用写
path('task/', TaskView.as_view())
  • 如上写法,为什么能够执行

(2)前置条件

  • 前端请求,一旦路径匹配成功,就会执行
    • TaskView.as_view()(request传入,)
  • 入口在
    • TaskView.as_view()—>执行结果—》View中有个as_view类的绑定方法
@classmethod
def as_view(cls, **initkwargs):def view(request, *args, **kwargs):self = cls(**initkwargs)res=self.dispatch(request, *args, **kwargs)return resreturn view
  • 执行结果是view 的内存地址: 请求来了,执行view(request)
path('books/', view)
  • 执行 View类中的as_view方法中的内层的view函数,路由匹配成功,本质是在执行
self.dispatch(request, *args, **kwargs)
  • self是谁的对象?
    • BookView的对象
  • 去BookView中dispatch,找不到
    • 去父类,View中找到了
  • View这个类的dispatch
def dispatch(self, request, *args, **kwargs):# 取出请求方式,转成小写,判断在不在列表中  get请求在if request.method.lower() in self.http_method_names:# handler=getattr(BookView的对象,'get')   # handler就是BookView类中的get方法handler = getattr(self, request.method.lower())else:handler = self.http_method_not_allowed# 执行 BookView类中的get方法 (request)return handler(request, *args, **kwargs)
  • 最终本质跟写fbv的执行流程一样

(3)最终结论

  • 什么请求方式,就会执行视图类中的什么方法
# 1 在路由中:path('index/',IndexView.as_view())# 2 请求来了---》路由匹配成功--》执行 IndexView.as_view()(request)-看View类的as_view的返回结果[可以加括号执行]---》猜:函数内存地址# 3 View类的as_viewdef as_view(cls, **initkwargs):def view(request, *args, **kwargs):self = cls(**initkwargs) # cls--》IndexViewreturn self.dispatch(request, *args, **kwargs)return view
# 4 IndexView.as_view() 本质就是 --》view--》内存函数view# 5 IndexView.as_view()(request)---》view(request)
# 6 本质 执行 self.dispatch--》self 是对象--》谁的对象?视图类的对象IndexView类的对象return self.dispatch(request, *args, **kwargs)# 7 IndexView没有dispatch--》View类中的dispatch# request 当次请求的requetsdef dispatch(self, request, *args, **kwargs):#1 取出请求方式,转成小写,判断在不在列表中  get请求在#2 self.http_method_names if request.method.lower() in self.http_method_names:# 3 反射:去 self IndexView类的对象中通过字符串get找属性或方法# 找到了get方法,赋值给了handlerhandler = getattr(self, request.method.lower())else:handler = self.http_method_not_allowed# 4 执行handler--》本质是get(request)# 执行了IndexView类中的get方法--》把request传进去了return handler(request, *args, **kwargs)

十、基于APIView的5个接口使用

1、视图类

from rest_framework.response import Response
from rest_framework.views import APIView  # # APIView继承了djagno原来的View
from app01.serializer import TaskSerializer
from app01.models import Taskclass TaskView(APIView):def get(self, request):tasks = Task.objects.all()# drf提供了序列化类serialized_tasks = TaskSerializer(instance=tasks, many=True)  # 序列化return Response({'code': 100, 'msg': '查询所有成功', 'results': serialized_tasks.data})def post(self, request):serialized_task = TaskSerializer(data=request.data)  # 反序列化if serialized_task.is_valid():  # 数据校验---》有些不合法的禁止serialized_task.save()  # 保存到数据库中return Response({'code': 100, 'msg': '创建成功'})class TaskDetailView(APIView):def get(self, request, *args, **kwargs):try:task = Task.objects.filter(id=kwargs['id']).first()serialized_task = TaskSerializer(instance=task, many=False)  # 序列化return Response({'code': 100, 'msg': '查询单个成功', 'result': serialized_task.data})except Exception:return Response({'code': 200, 'msg': '任务不存在'})def put(self, request, *args, **kwargs):try:task = Task.objects.filter(id=kwargs['id']).first()serialized_task = TaskSerializer(instance=task, data=request.data)  # 反序列化if serialized_task.is_valid():  # 数据校验---》有些不合法的禁止task.save()  # 重保存到数据库中return Response({'code': 100, 'msg': '更新成功'})except Exception:return Response({'code': 200, 'msg': '任务不存在'})def delete(self, request, *args, **kwargs):try:Task.objects.filter(id=kwargs['id']).delete()return Response({'code': 100, 'msg': '删除成功'})except Task.DoesNotExist:return Response({'code': 200, 'msg': '任务不存在'})

2、序列化类

from rest_framework import serializers
from .models import Taskclass TaskSerializer(serializers.ModelSerializer):class Meta:model = Taskfields = '__all__'

3、模型类

import uuid
from django.db import modelsclass UserLog(models.Model):ip = models.CharField(max_length=255)visit_time = models.DateTimeField(auto_now=True)method = models.CharField(max_length=32)path = models.CharField(max_length=64)user_agent = models.CharField(max_length=255)class Task(models.Model):task_id = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)task_name = models.CharField(max_length=255, db_index=True)task_time = models.DateTimeField(auto_now_add=True)task_desc = models.TextField()

4、路由

from django.urls import path
from app01 import viewsurlpatterns = [path('task/', views.TaskView.as_view()),path('task/<int:id>', views.TaskDetailView.as_view()),
]

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣118. 杨辉三角

Problem: 118. 杨辉三角 文章目录 题目描述思路复杂度Code 题目描述 思路 1.初始化状态&#xff1a;将创建的二维数组dp的第一列和主对角线上元素设为1&#xff1b; 2.状态的转移&#xff1a;从第一行、列起始&#xff0c;dp[i][j] dp[i - 1][j - 1] dp[i - 1][j] 复杂度 时…

FORM调用标准AP\AR\GL\FA界面

EBS FORM客户化界面有时候数据需要追溯打开AP\AR\GL\FA等界面&#xff1a; 一种打开日记账的方式&#xff1a; PROCEDURE SHOW_JOURNAL ISparent_form_id FormModule;child_form_id FormModule; BEGINclose_jrn;parent_form_id : FIND_FORM(:SYSTEM.CURRENT_FORM);COPY(TO…

OceanBase开发者大会实录 - 阳振坤:云时代的数据库

本文来自2024 OceanBase开发者大会&#xff0c;OceanBase 首席科学家阳振坤的演讲实录——《云时代的数据库》。完整视频回看&#xff0c;请点击这里 >> 在去年的开发者大会中&#xff0c;我跟大家分享了我对数据库产品和技术一些看法&#xff0c;包括单机分布式一体化&…

HarmonyOS 实战开发-MindSpore Lite引擎进行模型推理

场景介绍 MindSpore Lite 是一款 AI 引擎&#xff0c;它提供了面向不同硬件设备 AI 模型推理的功能&#xff0c;目前已经在图像分类、目标识别、人脸识别、文字识别等应用中广泛使用。 本文介绍使用 MindSpore Lite 推理引擎进行模型推理的通用开发流程。 基本概念 在进行开…

2024年Java JDK下载安装教程,附详细图文

文章目录 简介一、JDK的下载二、JDK的安装三、设置环境变量(不一定需要执行&#xff09; 简介 博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f34…

【Redis | 第十篇】Redis与MySQL保证数据一致性(两种解决思路)

文章目录 10.Redis和MySQL如何保证数据一致性10.1双写一致性问题10.2数据高度一致性10.3数据同步允许延时10.3.1中间件通知10.3.2延迟双删 10.Redis和MySQL如何保证数据一致性 10.1双写一致性问题 Redis作为缓存&#xff0c;它是如何与MySQL的数据保持同步的呢&#xff1f;特…

电商技术揭秘三十五:智能风控功能架构浅析

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘二十八&#xff1a;安全与合规性保障 电商技术揭秘二十九&#xff1a;电商法律合规浅析 电商技术揭秘三十&#xff1a;知识产权保…

MySQL随便聊----之MySQL的调控按钮-启动选项和系统变量

-------MySQL是怎么运行的 基本介绍 如果你用过手机&#xff0c;你的手机上一定有一个设置的功能&#xff0c;你可以选择设置手机的来电铃声、设置音量大小、设置解锁密码等等。假如没有这些设置功能&#xff0c;我们的生活将置于尴尬的境地&#xff0c;比如在图书馆里无法把手…

Vitis HLS 学习笔记--Syn Report解读(1)

目录 1. 介绍 2. 示例一 2.1 HLS 代码 2.2 Report 解读 2.2.1 General Information 2.2.2 Timing Estimate 2.2.3 Performance & Resource Estimates 2.2.4 HW interfaces 2.2.4.1 硬件接口报告 2.2.4.2 导出至 Vivado 中的 IP 2.2.4.3 Port-Level Protocols 端…

Flutter应用下拉菜单设计DropdownButtonFormField控件介绍

文章目录 DropdownButtonFormField介绍使用方法重点代码说明属性解释 注意事项 DropdownButtonFormField介绍 Flutter 中的 DropdownButtonFormField 是一个用于在表单中选择下拉菜单的控件。它是 DropdownButton 和 TextFormField 的组合&#xff0c;允许用户从一组选项中选择…

python之List列表

1. 高级数据类型 Python中的数据类型可以分为&#xff1a;数字型&#xff08;基本数据类型&#xff09;和非数字型&#xff08;高级数据类型&#xff09; 数字型包含&#xff1a;整型int、浮点型float、布尔型bool、复数型complex 非数字型包含&#xff1a;字符串str、列表l…

SkyWalking 自定义Span并接入告警

图容易被CSDN吞掉&#xff0c;我在掘金也发了&#xff1a;https://juejin.cn/post/7361821913398837248 我就是这么膨胀 最近在做 OpenAI API 套壳&#xff0c;当我使用 okhttp-sse 这个库进行流式内容转发的时候&#xff0c;我发现有些回调方法 SkyWalking 不能抓取到。这就…