04-drf视图层详细

news/发布时间2024/5/16 23:22:05

drf的request请求

这里的request请求是基于APIView的,也就是新的request
正常情况下,request请求分为:urlcoded、json、form-data,可以控制只接受哪一个请求

导入模块

from rest_framework.parsers import JSONParser, MultiPartParser, FormParser
模块 描述 请求
JSONParser 用于解析 JSON 请求内容。request.data 将被填充为一个数据字典。 application/json
FormParser 用于解析 HTML 表单内容。request.data 将被填充为一个数据 QueryDict。通常与 MultiPartParser 一起使用以完全支持 HTML 表单数据。 application/x-www-form-urlencoded
MultiPartParser 用于解析多部分 HTML 表单内容,支持文件上传。request.datarequest.FILES 将分别被填充为一个 QueryDict 和 MultiValueDict。通常与 FormParser 一起使用以完全支持 HTML 表单数据。 multipart/form-data

1)局部使用 视图层中 放在视图类属性中,不要放在方法中

from rest_framework.parsers import JSONParser, MultiPartParser, FormParserclass HeroView(APIView):# 放在视图类中 列表里面就是允许的请求parser_classes = [JSONParser]def get(self, request):passdef post(self, request):pass

2) 全局使用 settings里面设置

这个文件在哪里,在rest_framework.settings.py里面,自己扣出来该就行了。

后续drf要配置的东西,全部都放到这里即可

  1. 如果三个全部都使用(默认就是)
  2. 如果要限制某个使用,局部导入就行
  3. 局部优先级高于全局,也就是说,如果全局注释了 JSONParser, 局部允许了 JSONParser 那么还是会允许JSONParser的,其他一样的道理。
REST_FRAMEWORK = {'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser','rest_framework.parsers.MultiPartParser',],
}

关于request.data文件对象

  1. 能正常接受文件对象
  2. 不建议,通过request.data取文件对象,正常建议从request.FILES中去取文件数据。
    1. 为什么?
    2. 规范
def post(self, request):serializer = HeroSerializer(data=request.data)from_data = request.data from_files = request.FILESprint("从requet.data中", from_data)print("从request.FILES中", from_files)"""
从requet.data中 <QueryDict: {'age': ['4'], 'name': ['大乔'], 'addr': ['召唤师峡谷'], 'myfile': [<InMemoryUploadedFile: BB外键关系.png (image/png)>]}>
从request.FILES中 <MultiValueDict: {'myfile': [<InMemoryUploadedFile: BB外键关系.png (image/png)>]}>
"""

drf的response响应

# Response的源码
class Response(SimpleTemplateResponse):def __init__(self, data=None, status=None,template_name=None, headers=None,exception=False, content_type=None):

data 返回到响应体中

data的类型可以是:

  1. Python字典(dict
  2. 列表(list
  3. 序列化后的数据对象
  4. 查询集(QuerySet)的序列化结果
  5. 自定义的序列化结果

status 返回HTTP状态码

导入模块

from rest_framework import status

使用

# ...
from rest_framework import statusclass HeroView(APIView):def post(self, request):# ...return Response(data={"code": 201, "msg": "创建成功!"}, status=status.HTTP_201_CREATED)

image-20240415155717863

template_name (了解)

在DRF中,template_name参数是用于指定视图返回的HTML模板的名称。它通常用于基于类的视图中的APIViewViewSet,用于指定渲染HTML响应时要使用的模板文件。

例如,如果你有一个基于类的视图,你可以像这样设置template_name参数:

from rest_framework.views import APIView
from rest_framework.response import Responseclass MyAPIView(APIView):template_name = 'my_template.html'def get(self, request):# 一些逻辑处理return Response({'key': 'value'})

在这个例子中,当MyAPIView处理GET请求时,它会渲染名为my_template.html的模板,并将数据作为上下文传递给模板。

headers 响应头 可以自己定制

def get(self, request):# ...headers = {"name": "Ava", "age": 3}# 这是一个没有意义的响应头,只是做演示而已return Response({"code": 100, "msg": "成功", "results": serializer.data}, headers=headers)

image-20240415161058172

exception 异常 需要设置为布尔值 (了解)

exception参数是用于指示响应是否代表一个异常情况的布尔值。默认情况下,它是False,表示响应不是一个异常。当设置为True时,它表示响应代表一个异常情况。

在实际使用中,如果你的视图处理了一个异常,并且你想要返回一个异常响应,你可以创建一个Response对象,并将exception参数设置为True。这样,客户端在接收到这个响应时就会知道这是一个异常情况。

例如,在视图中处理一个异常并返回一个异常响应的示例:

from rest_framework.response import Responsedef my_view(request):try:# 这里是你的视图逻辑result = do_something()return Response(result)except Exception as e:# 如果发生异常,返回一个异常响应return Response(status=500, exception=True)

在这个示例中,如果do_something()函数抛出了一个异常,视图将返回一个带有500状态码的异常响应。通过将exception参数设置为True,客户端就会知道这是一个异常情况,而不是正常的成功响应。

举例说明

# ...
class HeroView(APIView):# ...def post(self, request):try:int("a")if serializer.is_valid():serializer.save()return Response(data={"code": 201, "msg": "创建成功!"}, status=status.HTTP_201_CREATED)except Exception as e:return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True, headers={"Error": e})

image-20240415162232275

-----------

响应格式

drf接口会根据客户端类型返回对应的格式,浏览器返回HTML格式,其他客户端返回json格式

注意:如果是返回的json格式,一般是建议指定 JSONOpenAPIRenderer 这样体验会好一些。

导入模块

from rest_framework.renderers import JSONOpenAPIRenderer, BrowsableAPIRenderer# JSONOpenAPIRenderer 用于按照 OpenAPI 规范将响应内容呈现为 JSON 格式。
# BrowsableAPIRenderer 用于将响应内容呈现为 HTML,用于可浏览的 API,提供了一个用户友好的界面,方便与 API 进行交互。

局部使用 视图层的类属性里面 不要放在方法里面

from rest_framework.renderers import JSONOpenAPIRenderer, BrowsableAPIRendererclass HeroView(APIView):# 放在类属性中,通过 render_classes = [类型指定即可]renderer_classes = [JSONOpenAPIRenderer]def get(self, request):..# 其他请求...

全局使用 settings里面设置

  1. 如果不做任何设置,默认是根据客户端关系返回
  2. 如果指定,那么浏览器和非浏览器都会按照指定格式(比如让浏览器返回json格式,而不是自带的drf api)
  3. 局部权重高于全局,也就是全局设置了返回JSONRenderer,局部设置了TemplateHTMLRenderer,一样按TemplateHTMLRenderer去返回
  4. 一般局部设置即可
REST_FRAMEWORK = {'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer','rest_framework.renderers.TemplateHTMLRenderer',]
}

2个视图基类 APIView和GenericAPIView

导入模块

from rest_framework.generics import GenericAPIView
from rest_framework.views import APIView

基于APIView + Response + 序列化类 写接口

class HeroDetailView(APIView):def get(self, request, pk):hero_instance = Hero.objects.get(pk=pk)serializer = HeroSerializer(instance=hero_instance)return Response({"code": 200, "msg": "ok", "result": serializer.data})def put(self, request, pk):hero_instance = Hero.objects.get(pk=pk)serializer = HeroSerializer(instance=hero_instance, data=request.data)if serializer.is_valid():serializer.save()return Response({"code": 200, "msg": "ok", "result": serializer.data})else:return Response({"code": 100, "msg": serializer.errors})def delete(self, request, pk):instance = get_object_or_404(Hero, pk=pk)instance.delete()return Response({"code": 100, "msg": "删除成功!"}, status=status.HTTP_204_NO_CONTENT)

基于GenericAPIView + Response + 序列化类 写接口

  1. 拿类属性通过方法去获取,而不要通过之前的方法。
  2. 如果要写其他模型的5个接口(有关联关系),所有代码不变,只需要改两个类属性即可

属性

# 查询所有对象
queryset = Hero.objects.all()  # 获取序列化类
serializer_class = HeroSerializer  

方法

 # 获取全部数据 
hero_instance = self.get_queryset() # 获取单个对象
hero_instance = self.queryset.filter(pk=pk).first()  # 很low 不建议hero_instance = self.get_object()  # 推荐的写法# 使用序列化类
serializer = self.get_serializer(instance=hero_instance, many=True)

GenericAPIView 的前端界面长这样

image-20240415172651424

# 基于GenericAPIView去写
class HeroDetailView(GenericAPIView):# 两个类属性queryset = Hero.objects.all()  # 全部serializer_class = HeroSerializer # 序列化类def get(self, request, pk):# hero_instance = self.queryset.filter(pk=pk).first() 不要这样写hero_instance = self.get_object()serializer = self.get_serializer(instance=hero_instance)return Response({"code": 200, "msg": "ok", "result": serializer.data})def put(self, request, pk):hero_instance = Hero.objects.get(pk=pk)serializer = HeroSerializer(instance=hero_instance, data=request.data)if serializer.is_valid():serializer.save()return Response({"code": 200, "msg": "ok", "result": serializer.data})else:return Response({"code": 100, "msg": serializer.errors})def delete(self, request, pk):self.get_object().delete()

有什么问题?代码重复

# 有部分重复的代码,应该可以尝试继续优化掉
hero_instance = self.get_object()
serializer = self.get_serializer(instance=hero_instance)

5个视图扩展类

导入模块

from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin
扩展类 对应方法 说明
CreateModelMixin post 创建单个实例,返回创建后的实例。
UpdateModelMixin put/patch 更新单个实例,返回修改后的实例。
DestroyModelMixin delete 删除单个实例,返回的结果为空。
ListModelMixin get 获取全部,返回一个queryset列表。
RetrieveModelMixin get/<int:pk>/ 获取单个,返回一个具体的实例。

通过5个视图扩展类 + GenericAPIView + 序列化类写接口

# 源码
class CreateModelMixin:def create(self, request, *args, **kwargs):serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True)  # 校验数据self.perform_create(serializer)headers = self.get_success_headers(serializer.data)return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)def perform_create(self, serializer):serializer.save()  # 和我们之前使用APIView的save() 一样 所以不需要我们写保存了,它内部调用了 perform_create 完成创建。 # 这里是校验字段的方法# 如果包含了数据库中不存在的字段,DRF 默认会忽略这些字段,不会引发错误。# 这是因为 DRF 默认情况下会忽略未知的字段,只处理已定义的字段。def get_success_headers(self, data):try:return {'Location': str(data[api_settings.URL_FIELD_NAME])}except (TypeError, KeyError):return {}

image-20240415190602607

代码

# ================ 五个视图扩展类
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixinclass HeroView(GenericAPIView, CreateModelMixin, ListModelMixin):queryset = Hero.objects.all() serializer_class = HeroSerializer""" 注释的是之前写的代码 现在可以不用写了hero_instance = self.get_queryset()serializer = self.get_serializer(instance=hero_instance, many=True)"""def get(self, request):return super().list(request)def post(self, request):return super().create(request)# 基于五个视图扩展类去写
class HeroDetailView(GenericAPIView, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin):# 两个类属性queryset = Hero.objects.all()  # 全部serializer_class = HeroSerializer # 序列化类def get(self, request, pk):return super().retrieve(request)def put(self, request, pk):return super().update(request)def delete(self, request, pk):return super().destroy(request)

关于return时候的super

方法 return的时候,需要返回父类的哪一个方法
get list
post create
get/int:pk/ retrieve
put update
delete destroy

有什么问题?代码重复

return super().list(request)
return super().create(request)
return super().retrieve(request)
return super().update(request)
return super().destroy(request)

9个视图子类

思考?为什么要有9个视图子类

  1. GenericAPIView + 对应的5个视图扩展类
    1. 5个
  2. GenericAPIView + CreateModelMixin + ListModelMixin
    1. 即创建一个和查询全部
    2. ListCreateAPIView
    3. 1个
  3. GenericAPIView + RetrieveModelMixin+ DestroyModelMixin
    1. 查询单条,删除单条
    2. RetrieveDestroyAPIView
    3. 1个
  4. GenericAPIView + RetrieveModelMixin + UpdateModelMixin
    1. 查询单条,修改单条
    2. RetrieveUpdateAPIView
    3. 1个
  5. GenericAPIView + RetrieveModelMixin + DestroyModelMixin
    1. 查询单条,既修改又删除
    2. GenericAPIView + RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin
    3. RetrieveUpdateDestroyAPIView
    4. 1个

思考:为什么没有更新和删除的组合?

因为更新和删除通常不会结合在一起使用,它们通常被认为是不同的操作,分别用于修改和删除资源。因此,DRF没有提供一个默认的视图类来结合这两个操作。

自己写一个Mixin

from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixinclass CreatListAPIView(GenericAPIView, CreateModelMixin, ListModelMixin):def get(self, request, *args, **kwargs):return super().list(request, *args, **kwargs)def post(self, request, *args, **kwargs):return super().create(request, *args, **kwargs)class HeroView(CreatListAPIView):queryset = Hero.objects.all() serializer_class = HeroSerializer

用模板写好的,我们直接使用

导入模块

from rest_framework.generics import CreateAPIView, ListAPIView, UpdateAPIView, DestroyAPIView, RetrieveAPIView
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView, RetrieveUpdateDestroyAPIView

五个方法

from rest_framework.generics import CreateAPIView, ListAPIView, UpdateAPIView, DestroyAPIView, RetrieveAPIView
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView, RetrieveUpdateDestroyAPIView# 查询所有 新增一条
class HeroView(ListCreateAPIView):queryset = Hero.objects.all()serializer_class = HeroSerializer# 查询 修改 删除 1条
class HeroDetailView(RetrieveUpdateDestroyAPIView):queryset = Hero.objects.all()serializer_class = HeroSerializer

视图集

  1. 如果要用视图集,一定要去修改路由,因为需要有映射关系。
  2. action是一个字典,字典的key是请求方式,字典的value是执行的方法。
  3. 我们可以自己定制映射关系,比如{"post": "login"},这样当发送post请求的时候,就执行login方法,不过需要继承 ViewSetMixin

通过视图集继续优化代码

# 视图层
from .serialinzer import HeroSerializer
from rest_framework.response import Response
from .models import Hero
from rest_framework.viewsets import ModelViewSetclass HeroView(ModelViewSet):queryset = Hero.objects.all()serializer_class = HeroSerializerclass HeroDetailView(ModelViewSet):queryset = Hero.objects.all()serializer_class = HeroSerializer
# 路由层
from django.urls import path
from .views import HeroView, HeroDetailViewurlpatterns = [path("heros/", HeroView.as_view({"get": "list", "post": "create"})),path("heros/<int:pk>/", HeroDetailView.as_view({"put":"retrieve", "get": "update", "delete": "destroy"}))
]

视图集源码分析

# 1 视图类:继承了APIView----》GenericAPIView
# 2 有5个方法---》继承了5个视图扩展类:CreateModelMixinRetrieveModelMixinDestroyModelMixinListModelMixinUpdateModelMixin
# 3  写没写 get put  post delete--》使用映射get---》listget---》retrieveput---》updatedelete--》destroypost-->create
# 4 继承了5个视图扩展类和  GenericViewSet 【不是GenericAPIView】# 5 GenericViewSet:ViewSetMixin+GenericAPIView# 6 ViewSetMixin 核心---》只要继承它--》路由写法就变了--》必须加action--》-action是请求方式和视图类中方法的映射关系# 7 以后只要继承ViewSetMixin的视图类1 as_view 必须加action做映射2 视图类中,可以写任意名的方法,只要做好映射,就能执行# 8 ViewSetMixin源码分析--》通过重写as_view使得路由写法变了@classonlymethoddef as_view(cls, actions=None, **initkwargs):# 0 跟APIView的as_view差不多# 1  actions must not be empty,如果为空抛异常# 2 通过反射把请求方式同名的方法放到了视图类中--》对应咱们的映射def view(request, *args, **kwargs):self = cls(**initkwargs)# actions 咱们传入的字典--》映射关系# {'get': 'list', 'post': 'create'}for method, action in actions.items():# method=get    action=list# method=post   action=create# 视图类对象中反射:list 字符串--》返回了 list方法# handler就是list方法handler = getattr(self, action)# 把handler:list方法 通过反射--》放到了视图类的对象中、# method:get# 视图类的对象中有个get--》本质是listsetattr(self, method, handler)return self.dispatch(request, *args, **kwargs) # APIView的dispatchreturn csrf_exempt(view)

继承ViewSetMixin,定制映射关系

注意,ViewSetMixin需要是直接父类,也就是要写在括号的左边,因为它重写了as_view,如果放在右边,能找到as_view,就无法执行action而触发报错。

# 常规写法
from rest_framework.viewsets import ViewSetMixin
from rest_framework.generics import GenericAPIViewclass Game(ViewSetMixin, GenericAPIView):def login(self, request):return Response({"code": 100, "msg": "登录成功!"})"""
(<class 'app01.views.Game'>, 
<class 'rest_framework.viewsets.ViewSetMixin'>,
<class 'rest_framework.generics.GenericAPIView'>, 
<class 'rest_framework.views.APIView'>, 
<class 'django.views.generic.base.View'>, 
<class 'object'>)
"""# 查看源码
class ViewSet(ViewSetMixin, views.APIView):"""The base ViewSet class does not provide any actions by default."""pass

ViewSet = ViewSetMixin, GenericAPIView

# 更新写法
from rest_framework.viewsets import ViewSetclass Game(ViewSet):def login(self, request):return Response({"code": 100, "msg": "登录成功!"})

视图集下常用的类

# 五个接口
class ModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet):# 查询1条,查询全部  get/<int:pk>/  get 
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet):# 定制映射关系,路由写法要修改 --> action= {"post": "login"} 
class ViewSet(ViewSetMixin, views.APIView):"""The base ViewSet class does not provide any actions by default."""pass# 路由写法要修改
# 继承自 GenericAPIView 与 ViewSetMixin,在实现了调用 as_view() 时传入字典(如 {'get':'list'})的映射处理工作的同时
# 还提供了 GenericAPIView 提供的基础方法,可以直接搭配 Mixin 扩展类使用。
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):"""The GenericViewSet class does not provide any actions by default,but does include the base set of generic view behavior, such asthe `get_object` and `get_queryset` methods."""pass

重写

查询部分数据,重写GenericAPIView.get_queryset

class HeroView(ListCreateAPIView):queryset = Hero.objects.all()serializer_class = HeroSerializerdef get_queryset(self):# 对get_queryset进行重写,查询id大于20小于40的结果queryset = self.queryset.filter(id__gt="20", id__lt="40")return queryset

根据请求执行不同序列化类,重写GenericAPIView.get_serializer_class

def get_serializer_class(self):if self.request.method == "GET":return ASerializer  # 替换 "a序列化类" 为实际的序列化类elif self.request.method == "POST":return BSerializer  # 替换 "b序列化类" 为实际的序列化类

新增数据后,返回指定消息给客户端 重写 CreateModelMixin.create

def create(self, request, *args, **kwargs):serializer = self.get_serializer(data=request.data)serializer.is_valid(raise_exception=True)serializer.save()return Response({"code": 201, "msg": "新增成功!", "result": serializer.data})

控制只能发送某一个请求

class HeroDetailView(RetrieveUpdateDestroyAPIView):# 通过这个指定,里面填写允许的请求方式, 在views里面http_method_names = ["get",]queryset = Hero.objects.all()serializer_class = HeroSerializer
# HeroDetailView.__mro__
(<class 'app01.views.HeroDetailView'>, <class 'rest_framework.generics.RetrieveUpdateDestroyAPIView'>,<class 'rest_framework.mixins.RetrieveModelMixin'>, <class 'rest_framework.mixins.UpdateModelMixin'>,<class 'rest_framework.mixins.DestroyModelMixin'>,<class 'rest_framework.generics.GenericAPIView'>, <class 'rest_framework.views.APIView'>, <class 'django.views.generic.base.View'>, <class 'object'>)

路由

自动生成路由SimpleRouter

from django.urls import path
from .views import HeroView
# 1 导入模块
from rest_framework.routers import SimpleRouter# 实例化得到对象
router = SimpleRouter()
# 调用对象的方法
router.register("heros", HeroView, basename="HeroView")urlpatterns = [] # 把生成的路由放进去路径里面
urlpatterns += router.urls

自动生成路由DefaultRouter

和SimpleRouter用法一样,只是会多一个api-root,后面路径多了看到的效果会更加明显。

admin/
app01/ ^heros/$ [name='HeroView-list']
app01/ ^heros\.(?P<format>[a-z0-9]+)/?$ [name='HeroView-list']
app01/ ^heros/(?P<pk>[^/.]+)/$ [name='HeroView-detail']
app01/ ^heros/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='HeroView-detail']
app01/ [name='api-root']
app01/ <drf_format_suffix:format> [name='api-root']# 访问app01路径,之前会报错,现在会返回一个json
{"heros": "http://127.0.0.1:8000/app01/heros/"
}

使用action定制详细路由

导入模块

from rest_framework.decorators import action

代码

# 视图层
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import actionclass Game(ViewSetMixin, GenericAPIView):@action(methods=['POST'], detail=False)def login(self, request):return Response({"code": 100, "msg": "登录成功!"})# 路由层 有两个自动生成才能看到效果
from django.urls import path
from .views import HeroView, HeroDetailView, Game
from rest_framework.routers import SimpleRouter, DefaultRouterrouter = DefaultRouter()
router.register("heros", HeroView, basename="HeroView")reouter1 = SimpleRouter()
reouter1.register("game", Game, basename="Game")urlpatterns = [] urlpatterns += router.urls
urlpatterns += reouter1.urls

img

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

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

相关文章

缓存数据“消失”之谜

吃一堑,长一智。吃一堑,长一智。“邪门!真是邪门!”自从踏入 Go 的领域之后,奇事怪事接连不断。很多看上去似乎没啥问题的代码,可就是有问题,可怎么也看不出问题所在。问题背景 事情是这样的:有两个流程和一个缓存数据: 流程一:接收 kafka 数据,解析模型数据,并存入…

Python调用微信OCR识别文字和坐标

原理 在看雪看到一篇文章:逆向调用QQ截图NT与WeChatOCR-软件逆向。里面说了怎么调用微信和QQ本地的OCR模型,还有很详细的分析过程。 我稍微看了下文章,多的也看不懂。大概流程是使用mmmojo.dll这个dll来与WeChatOCR.exe做通信的,也是用它来启动和关闭WeChatOCR.exe进程的。…

泰国股票盘搭建【TG:@Gangguhk】

功能最强大的股票配资系统 我们的股票配资系统是由拥有10年项目开发经验的资深技术人员,针对股票配资市场情况及股票投资者需要而精心研发,可同时运行于手机端、电脑端的多屏杠杆融资风控管理系统。功能包括自设配资额度、多级代理、交易管理、客户管理、警戒平仓、系统监控、…

openGauss AI4DB-数据库自治运维

AI4DB: 数据库自治运维 如上文所述,AI4DB主要用于对数据库进行自治运维和管理,从而帮助数据库运维人员减少运维工作量。在实现上,DBMind的AI4DB框架具有监控和服务化的性质,同时也提供即时AI工具包,提供开箱即用的AI运维功能(如索引推荐)。AI4DB的监控平台以开源的Prome…

服务端测试开发必备技能:Mock测试

什么是mock测试 Mock 测试就是在测试活动中,对于某些不容易构造或者不容易获取的数据/场景,用一个Mock对象来创建以便测试的测试方法。 Mock测试常见场景无法控制第三方系统接口的返回,返回的数据不满足要求 依赖的接口还未开发完成,就需要对被测系统进行测试Mock测试的缺点…

03、OSPF与BFD联动

OSPF与BFD联动定义 双向转发检测BFD(Bidirectional Forwarding Detection)是一种用于检测转发引擎之间通信故障的检测机制。 BFD对两个系统间的、同一路径上的同一种数据协议的连通性进行检测,这条路径可以是物理链路或逻辑链路,包括隧道。 OSPF与BFD联动就是将BFD和OSPF协…