DRF从入门到精通四(视图基类、GenericAPIView的视图扩展类、视图子类、视图集父类、子类)

文章目录

  • 前言
  • 一、视图基类
    • APIView基类
    • GenericAPIView通用视图基类
  • 二、GenericAPIView的视图拓展类
    • 1.ListModelMixin
    • 2.CreateModelMixin
    • 3.RetrieveModelMixin
    • 4.UpdateModelMixin
    • 5.DestroyModelMixin
  • 三、GenericAPIView的视图子类
    • ListCreateAPIView
    • RetrieveUpdateDestroyAPIView
  • 四、视图集父类
    • ViewSet
    • GenericViewSet
  • 五、视图集子类
    • ModelViewSet
    • ReadOnlyModelViewSet

前言

Django REST framwork 提供的视图的主要作用:

  • 控制序列化器的执行(检验、保存、转换数据)
  • 控制数据库查询的执行

虽说视图也可以基于FBV模式来进行开发,但是使用CBV能够让我们避免很多重复代码,类具备继承、封装、多态等等,而DRF也给我们提供了非常丰富的视图组件

一、视图基类

DRF提供了众多通用的视图基类与拓展类,以供我们简化视图的编写。

APIView基类

APIView是DRF提供的所有视图的基类(父类),而APIView则继承自Django的View作为父类
APIViewView不同之处在于:

  • 传入到视图方法中的REST framework的Request对象,而不是Django的HttpResponse对象
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。

支持定义的类属性(部分):

属性名定义方式作用
authentication_classes列表或元祖权限检查类
permissoin_classes列表或元祖列表或元祖
throttle_classes列表或元祖流量控制类

APIView中仍以常规的类视图定义方法来实现get() post() 或者其它方法来处理请求;
例如:

	from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom .serializer import BookSerializerfrom . import modelsclass BookView(APIView):def get(self, request):book = models.Book.objects.all()ser = BookSerializer(instance=book, many=True)return Response(ser.data)

这也就是我们平常所编写的,获取数据、传入序列化器、得到序列化后的内容


GenericAPIView通用视图基类

	from rest_framework.generics import GenericAPIViewclass BookView(GenericAPIView):queryset = models.Book.objects.all()serializer_class = BookSerializer

继承自APIView,主要增加了操作序列化器和数据库查询的方法,作用是为了Mixin扩展类的执行提供方法支持,通常在使用时,可搭配一个或多个Mixin扩展类。

需要使用的类属性:

  • queryset:指明使用的数据查询集
  • serializer_class:指明视图使用的序列化器

内部常用的方法:
get_serializer_class(self)

  • 当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了
  • 返回序列化器类,默认返回serializer_class

一般不会调用
get_queryset():获取查询集(等同于获取queryset类属性的值)

	class BookView(GenericAPIView):queryset = models.Book.objects.all()serializer_class = BookSerializer'''提供了拓展性,可以定制返回内容'''def get_serializer_class(self):if self.request.method == 'GET':return models.Book.objects.all()else:return models.Publish.objects.all()def get(self, request):obj_list = self.get_queryset()

get_serializer(self,*args,**kwargs)

返回序列化器对象,主要用来提供给Mixin拓展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。

注意:该方法在提供序列化器对象的时候,会向序列化器对象的context属性补充三个数据:request、format、viwe,这三个数据对象可以在定义序列化器时使用。

  • request 当前视图的请求对象
  • view 当前请求的类视图对象
  • format 当前请求期望返回的数据格式
	class BookView(GenericAPIView):queryset = models.Book.objects.all()serializer_class = BookSerializerdef get(self, request):obj_list = self.get_queryset()ser = self.get_serializer(instance=obj_list, many=True)  # 同正常调用序列化器一样return Response(ser.data)

get_object():返回详情视图所需的模型类数据对象(方法必须要有一个形参名为pk),若详情访问的模型类对象不存在,会返回404

	class BookDetailView(GenericAPIView):queryset = models.Book.objects.all()serializer_class = BookSerializerdef get(self, request, *args, **kwargs):  # kwargs内必须有一个key名为pkobj = self.get_object() # 获取某个对象,它的主键值与kwargs里的pk值相等ser = self.get_serializer(instance=obj) # 传入序列化器return Response(ser.data)

其他可以设置的属性

  • pagination_class 指明分页控制类
  • filter_backends 指明过滤控制后端

整体代码展示

	'''继承GenericAPIView+序列化类+Response'''from rest_framework.generics import GenericAPIViewfrom rest_framework.response import Responseclass BookView(GenericAPIView):queryset = models.Book.objects.all()serializer_class = BookSerializerdef get(self, request):obj_list = self.get_queryset()ser = self.get_serializer(instance=obj_list, many=True)return Response(ser.data)def post(self, request):ser = self.get_serializer(data=request.data)if ser.is_valid():ser.save()return Response(ser.data)else:return Response(ser.errors)class BookDetailView(GenericAPIView):queryset = models.Book.objects.all()serializer_class = BookSerializer'''提供了拓展性,可以定制返回内容'''def get_serializer_class(self):if self.request.method == 'GET':return models.Book.objects.all()else:return models.Publish.objects.all()def get(self, request, *args, **kwargs):  # kwargs内必须有一个key名为pkobj = self.get_object() # 获取某个对象,它的主键值与kwargs里的pk值相等ser = self.get_serializer(instance=obj) # 传入序列化器return Response(ser.data)def put(self, request, *args, **kwargs):obj = self.get_object()if obj:ser = self.get_serializer(instance=obj,data=request.data)if ser.is_valid():ser.save()return Response(ser.data)else:return Response(ser.errors)else:return Response('修改的数据不存在')def delete(self, request, *args, **kwargs):self.get_object().delete()return Response('')

序列化类

	class BookSerializer(serializers.ModelSerializer):class Meta:model = models.Bookfields = ['name', 'price', 'publish', 'authors', 'publish_detail', 'author_list']extra_kwargs = {'publish': {'write_only': True},'authors': {'write_only': True},'publish_detail': {'read_only': True},'author_list': {'read_only': True},}

可能暂时没有看出GenericAPIView这个类带给我们的优势,因为我们这个GenericAPIView是作为基类使用的,需要搭配Mixin拓展类一起使用。


二、GenericAPIView的视图拓展类

提供了几种后端视图(对数据资源机械能增删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来服用代码,减少自己编写的代码量。

这五个拓展类需要搭配GenericAPIView父类,因为五个拓展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

在实例开始前,准备序列化器:

	from . import modelsfrom rest_framework import serializersclass BookSerializer(serializers.ModelSerializer):class Meta:model = models.Bookfields = ['name', 'price', 'publish', 'authors', 'publish_detail', 'author_list']extra_kwargs = {'publish': {'write_only': True},'authors': {'write_only': True},'publish_detail': {'read_only': True},'author_list': {'read_only': True},}

路由配置

	我这里使用了路由分发,include'总路由'from django.contrib import adminfrom django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('api/v1/', include('app01.urls')),]'子路由app01/urls.py'from django.urls import pathfrom . import viewsurlpatterns = [path('books/',views.BookView.as_view()),path('books/<int:pk>',views.BookDetailView.as_view()),]

1.ListModelMixin

列表视图拓展类,提供list(reqeust,*args,**kwargs)方法快速实现列表视图,返回200状态码。
该Mixin的list方法会对数据进行过滤和分页。

源码

	class ListModelMixin:"""List a queryset."""def list(self, request, *args, **kwargs):# 获取经过过滤的查询集queryset = self.filter_queryset(self.get_queryset())# 如果启用了分页,对查询集进行分页处理page = self.paginate_queryset(queryset)if page is not None:# 使用序列化器对分页后的数据进行序列化serializer = self.get_serializer(page, many=True)# 返回分页响应return self.get_paginated_response(serializer.data)#如果没有启用分页,直接对查询集进行序列化serializer = self.get_serializer(queryset, many=True)# 返回非分页的响应return Response(serializer.data)

举例说明:
未调用list方法前:

	from rest_framework.generics import GenericAPIViewclass BookView(GenericAPIView):queryset = models.Book.objects.all()  # 指定序列化的数据(GenericAPIView内部会调用该方法)serializer_class = BookSerializer #指定序列化器def get(self, request):obj_list = self.get_queryset()  # 获取需要序列化的数据(等同于获取了queryset的值)ser = self.get_serializer(instance=obj_list, many=True) #将序列化数据传入序列化器,得到序列化器的对象return Response(ser.data)

调用list方法后:

	from rest_framework.generics import GenericAPIViewfrom rest_framework.mixins improt ListModelMixinclass BookView(GenericAPIView,ListModelMixin):queryset = models.Book.objects.all()  # 指定序列化的数据(GenericAPIView内部会调用该方法)serializer_class = BookSerializer #指定序列化器def get(self, request):'内部list方法会将需要序列化的数据传给序列化器,然后返回序列化器独享data数据'return super().list(request)

这两种方式实现的效果相同,但是明显下面代码会少一些。

在这里插入图片描述


2.CreateModelMixin

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。
如果序列化器对前端发送的数据验证失败,返回400错误。

源码

	class CreateModelMixin:"""Create a model instance."""def create(self, request, *args, **kwargs):# 使用请求中的数据创建序列化器'传递前端发送过来的数据,获取序列化器对象'serializer = self.get_serializer(data=request.data)# 验证序列化器的数据是否有效,如果无效将引发异常'机械校验,如果校验失败则直接抛出异常'serializer.is_valid(raise_exception=True)# 调用 perform_create 方法执行实际的创建操作'调用下面的方法,将序列化器对象传入'self.perform_create(serializer)# 获取成功创建后的响应头信息headers = self.get_success_headers(serializer.data)# 返回包含新创建实例数据的响应,HTTP 状态码为 201 Createdreturn Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)def perform_create(self, serializer):# 调用序列化器的 save 方法,将数据保存到数据库中'由于我们序列化器继承的是ModelSerializer,所以不需要重写create方法就能将数据新增'serializer.save()def get_success_headers(self, data):# 获取成功创建后的响应头信息,通常是新创建实例的位置 URLtry:return {'Location': str(data[api_settings.URL_FIELD_NAME])}except (TypeError, KeyError):return {}

使用方式:

	from rest_framework.mixins import CreateModelMixin,ListModelMixinclass BookView(GenericAPIView,CreateModelMixin,ListModelMixin):queryset = models.Book.objects.all()serializer_class = BookSerializerdef get(self, request):return super().list(request)def post(self, request):return super().create(request)

在这里插入图片描述

此时我们的代码已经开始越写越少了,因为继承的类已经帮助我们调用了正常需要调用的代码,此后新增直接调用即可,但也不排除少数情况需要我们重写create方法。


3.RetrieveModelMixin

详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。
如果存在,返回200, 否则返回404。

源码

	class RetrieveModelMixin:"""Retrieve a model instance."""def retrieve(self, request, *args, **kwargs):# 获取要检索的模型实例instance = self.get_object()# 使用序列化器对模型实例进行序列化serializer = self.get_serializer(instance)# 返回包含序列化数据的响应return Response(serializer.data)

本质就是在kwargs获取一个key为pk的关键字的值,然后在queryset查询集内获取pk值相同的对象传入序列化器,响应序列化后的数据。

使用方式:

	from rest_framework.mixins import RetrieveModelMixinclass BookDetailView(GenericAPIView, RetrieveModelMixin):queryset = models.Book.objects.all()serializer_class = BookSerializerdef get(self, request, *args, **kwargs):'retrieve方法本质上还是调用了self.get_object方法拿到对象传给序列化器,然后返回序列化器的data数据'return super().retrieve(request,*args,**kwargs)

在这里插入图片描述


4.UpdateModelMixin

更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。

成功返回200,序列化器校验数据失败时,返回400错误。

源码

	class UpdateModelMixin:"""Update a model instance."""def update(self, request, *args, **kwargs):# 获取是否为部分更新的标志(partial)partial = kwargs.pop('partial', False)# 获取要更新的模型实例'获取需要更改的数据的对象'instance = self.get_object()# 使用序列化器对模型实例进行更新'将对象,数据传入序列化器'serializer = self.get_serializer(instance, data=request.data, partial=partial)serializer.is_valid(raise_exception=True)# 调用 perform_update 方法执行实际的更新操作self.perform_update(serializer)# 如果已经应用了 'prefetch_related' 到查询集,需要强制使模型实例的预取缓存无效if getattr(instance, '_prefetched_objects_cache', None):instance._prefetched_objects_cache = {}#返回包含更新后序列化数据的响应return Response(serializer.data)def perform_update(self, serializer):# 调用序列化器的 save 方法,将更新后的数据保存到数据库中'序列化器接收了instance对象,执行save后会执行内部的update方法'serializer.save()def partial_update(self, request, *args, **kwargs):# 部分更新的快捷方法,设置 'partial' 标志为 Truekwargs['partial'] = Truereturn self.update(request, *args, **kwargs)

使用方式:

	from rest_framework.mixins import UpdateModelMixinclass BookDetailView(GenericAPIView, UpdateModelMixin):queryset = models.Book.objects.all()serializer_class = BookSerializerdef put(self, request, *args, **kwargs):'内部执行原理:先获取某个对象,然后一并将request.data数据传给序列化器,拿到序列化器对象的data数据'return super().update(request, *args, **kwargs) #UpdateModelMixin类的内部的方法

在这里插入图片描述


5.DestroyModelMixin

删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
成功返回204,不存在返回404。

源码

	class DestroyModelMixin:"""Destroy a model instance."""def destroy(self, request, *args, **kwargs):# 获取要删除的模型实例'获取需要删除的对象'instance = self.get_object()# 调用 perform_destroy 方法执行实际的删除操作'执行删除操作'self.perform_destroy(instance)# 返回空内容的响应,HTTP 状态码为 204 No Content,表示成功删除return Response(status=status.HTTP_204_NO_CONTENT)def perform_destroy(self, instance):# 调用模型实例的 delete 方法,从数据库中删除该实例instance.delete()

使用方式:

	from rest_framework.mixins import DestroyModelMixinclass BookDetailView(GenericAPIView,DestroyModelMixin):queryset = models.Book.objects.all()serializer_class = BookSerializerdef delete(self, request, *args, **kwargs):return super().destroy(request, *args, **kwargs) # DestroyModelMixin类内部方法

在这里插入图片描述

此时我们整体代码相对平常编写的视图已经减少了很多,并且能够正常实现功能。下面了解到的将会使我们的代码更加简洁、并保证了接口使用


三、GenericAPIView的视图子类

GenericAPIView提供了5个视图拓展类以及9个视图子类,上面5个拓展类以及介绍了,下面来介绍视图子类

GenericAPIView的视图子类是依赖于视图拓展类的,视图子类内部本质就是继承了视图拓展,而且它内部为我们放在了对应的方法里面,所以我们只要使用了视图子类,便无需再写执行请求的方法。

ListCreateAPIView

执行查询所有数据与新增数据,我们可以继承ListCreateAPIView这个视图子类

源码

	'继承了GenericAPIView视图基类,以及2个视图拓展类'class ListCreateAPIView(mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView):"""Concrete view for listing a queryset or creating a model instance."""'与我们使用的视图拓展类时代码相同,不过省略了我们定义请求方法的步骤'def get(self, request, *args, **kwargs):# 处理 HTTP GET 请求,调用 ListModelMixin 中的 list 方法return self.list(request, *args, **kwargs)def post(self, request, *args, **kwargs):# 处理 HTTP POST 请求,调用 CreateModelMixin 中的 create 方法return self.create(request, *args, **kwargs)

使用方式:

	from rest_framework.generics import ListCreateAPIViewclass BookView(ListCreateAPIView):'ListCreateAPIView类里面具备了get方法与post方法,请求来的时候回调该类的get或者post请求''而该类的内部又继承了GenericAPIView、ListModelMixin、CreateModelMixin'queryset = models.Book.objects.all()serializer_class = BookSerializer

使用效果:下面测试的是GET请求,而POST请求也是可以处理的,和我们上面效果相同。

在这里插入图片描述


RetrieveUpdateDestroyAPIView

该类内部具备了get(查询单个对象数据)、put、patch、delete方法。同样也对应继承了3个拓展类

源码

	class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,GenericAPIView):"""Concrete view for retrieving, updating or deleting a model instance."""def get(self, request, *args, **kwargs):# 处理 HTTP GET 请求,调用 RetrieveModelMixin 中的 retrieve 方法return self.retrieve(request, *args, **kwargs)def put(self, request, *args, **kwargs):# 处理 HTTP PUT 请求,调用 UpdateModelMixin 中的 update 方法return self.update(request, *args, **kwargs)def patch(self, request, *args, **kwargs):# 处理 HTTP PATCH 请求,调用 UpdateModelMixin 中的 partial_update 方法return self.partial_update(request, *args, **kwargs)def delete(self, request, *args, **kwargs):# 处理 HTTP DELETE 请求,调用 DestroyModelMixin 中的 destroy 方法return self.destroy(request, *args, **kwargs)

通过内部具备了处理请求的方法,然后又继承了拓展类,所以我们只需要填写3行的固定代码即可实现这3个接口的使用

使用方式:

	from rest_framework.generics import RetrieveUpdateDestroyAPIViewclass BookDetailView(RetrieveUpdateDestroyAPIView):queryset = models.Book.objects.all()serializer_class = BookSerializer

在这里插入图片描述

上面的两种方式就集成了5个接口的使用,且不需要我们手动定义处理请求的方法,而如果我们不想一下开启这么多接口,那么不妨使用下面的子类

  1. from rest_framework.generics import ListAPIView:具备了查询所有数据的get方法
  2. from rest_framework.generics import CreateAPIView:具备新增数据的post方法
  3. from rest_framework.generics import RetrieveAPIView:内部具备了查询单个对象的get方法
  4. from rest_framework.generics import UpdateAPIView:内部具备了修改单个对象的put方法
  5. from rest_framework.generics import DestoryAPIView:具备了删除单个对象的delete方法
  6. from rest_framework.generics import RetrieveUpdateAPIView:具备了查询、修改单个对象的get、put方法
  7. from rest_framework generics import RetrieveDestroyAPIView:具备了查询、删除单个对象的get、delete方法

总结:

综合上面我们使用过的两种方法,加上这些总共9个视图子类,而它们内部全部需要集成GenericAPIView作为基类,然后右继承了一些扩展类放在对应的请求方法里面,实现了我们只需要继承一些子类就能实现更多接口。

但是由于get请求无法区分是查询全部内容还是单个内容,所以我们不得不拆分两个类来处理,下面了解到的视图集可以很好的解决这个问题


四、视图集父类

在开始了解视图集之前,我们应该先了解一些视图集的父类

ViewSet

继承子APIView与ViewSetMixin,作用也与APIView基本类似, 提供了身份认证、权限校验、流量管理等。

ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典,如{'get':'list'}的映射处理工作,这表示:将get请求交给视图里面的list方法来处理

在ViewSet中,没有提供任何方法,需要我们自己手动定义方法

	from rest_framework import viewsetsclass BookViewSet(viewsets.ViewSet):def list(self,reqeust):books = models.Book.objects.all()ser = BookSerializer(intance=books,many=True)return Response(ser.data)def retrieve(self,request,pk=None):try:books = models.Book.objects.get(id=pk)except models.Book.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)ser = BookSerializer(books)return Response(ser.data)

路由配置

	from django.urls import pathfrom . import viewsurlpatterns = [path('books/', views.BookViewSet.as_view({'get': 'list'})),path('books/<int:pk>', views.BookViewSet.as_view({'get': 'retrieve'})),]

GenericViewSet

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView

	from rest_framework.viewsets import GenericViewSetfrom rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixinclass BookView(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):queryset = models.Book.objects.all()serializer_class = BookSerializer

路由配置

	urlpatterns = [path('books/', views.BookView.as_view({'get': 'list','post':'create'})),path('books/<int:pk>', views.BookView.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),]

此时虽然可以一个类实现5个接口,但是需要我们手动继承的类未免太多,所以我们接下来会了解到一种只需要继承一个类,实现5个接口,并且我们只需要定义一个类即可。


五、视图集子类

ModelViewSet

继承自GenericViewSet,同时也继承了ListModelMixinRetrieveModelMixinCreateModelMixinUpdateModelMixinDestoryModelMixin

视图层

	from rest_framework.viewsets import ModelViewSetclass BookModelView(ModelViewSet):queryset = models.Book.objects.all()serializer = BookSerializer

ModelViewSet最主要的就是继承了GenericViewSet而它又继承了ViewSetMixin类。那么只要我们继承了ViewSetMixin类,那么路由调用视图类的方式就要发生改变,上面两个实例就可以说明

如下:

	urlpatterns = [path('books/', views.BookModelView.as_view({'get': 'list','post':'create'})),path('books/<int:pk>', views.BookModelView.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),]

ReadOnlyModelViewSet

只读的视图集,它具备了查询数据的接口,单个对象查询、所有对象查询。

继承自GenericAPIView,同时包括了:ListModelMixinRetrieveModelMixin


在视图集中自定义方法

在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。

	from rest_framework.viewsets import ModelViewSetclass BookModelView(ModelViewSet):queryset = models.Book.objects.all()serializer = BookSerializerdef login(self,reqeust):'登录功能'return Response({'message':'登录成功'})

路由配置

	urlpatterns = [path('books/', views.BookModelView.as_view({'get': 'list','post':'create'})),path('books/<int:pk>', views.BookModelView.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),path('login/',views.BookModelView.as_view({'get':'login'})),]

匹配上路由以后,如果是get请求则交给视图集里面的login方法来处理。

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

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

相关文章

中庸 原文与译文

《中庸》是中国古代论述人生修养境界的一部道德哲学专著&#xff0c;是儒家经典著作之一&#xff0c;原属《礼记》第三十一篇&#xff0c;相传为战国时期子思所作。 其内容肯定“中庸”是道德行为的最高标准&#xff0c;认为“至诚”则达到人生的最高境界&#xff0c;并提出“…

C语言中关于if else的理解

if else我们可以理解为 if(条件1) //如果条件1成立 语句1&#xff1b; //执行语句1 else //如果条件1不成立 语句2; //执行语句2 这是一个经典的if els…

大数据技术学习笔记(十一)—— Flume

目录 1 Flume 概述1.1 Flume 定义1.2 Flume 基础架构 2 Flume 安装3 Flume 入门案例3.1 监控端口数据3.2 实时监控单个追加文件3.3 实时监控目录下多个新文件3.4 实时监控目录下的多个追加文件 4 Flume 进阶4.1 Flume 事务4.2 Flume Agent 内部原理4.3 Flume 拓扑结构4.3.1 简单…

1861_什么是H桥

Grey 全部学习内容汇总&#xff1a; GitHub - GreyZhang/g_hardware_basic: You should learn some hardware design knowledge in case hardware engineer would ask you to prove your software is right when their hardware design is wrong! 1861_什么是H桥 H桥电路可以…

蓝桥杯c/c++程序设计——数位排序

数位排序【第十三届】【省赛】【C组】 题目描述 小蓝对一个数的数位之和很感兴趣&#xff0c;今天他要按照数位之和给数排序。 当两个数各个数位之和不同时&#xff0c;将数位和较小的排在前面&#xff0c;当数位之和相等时&#xff0c;将数值小的排在前面。 例如&#xff0…

reactive和TypeScript标注数据类型-ts使用方法

一、vite项目中<script setup lang"ts"> : lang"ts" 是表明支持ts校验&#xff08;ts 全称typescript,是es6语法&#xff0c;是javascript的超集强类型编程语言&#xff0c;类似java&#xff0c;定义变量类型后&#xff0c;赋值类型不一致&#xff0…

创建一台可以安装linux系统的虚拟机的流程

1、打开vmware-->点击左上角文件-->新建虚拟机-->自定义 2、默认选择&#xff0c;直接下一步 3、选中稍后安装操作系统&#xff0c;然后下一步 4、选中Linux&#xff0c;然后下拉框选择CentOS7(64位) 5、设置虚拟机名称及存储位置 6、设置虚拟机处理器数量及核心数 7、…

选择排序之C++实现

描述 选择排序&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。它的基本思想是&#xff1a;每一轮从待排序的数据中选择最小&#xff08;或最大&#xff09;的一个元素&#xff0c;然后与待排序数据的第一个元素交换位置。对剩余未排序的数据重复这个过程&a…

【【IIC模块Verilog实现---用IIC协议从FPGA端读取E2PROM】】

IIC模块Verilog实现–用IIC协议从FPGA端读取E2PROM 下面是 design 设计 I2C_dri.v module IIC_CONTROL #(parameter SLAVE_ADDR 7b1010000 , // E2PROM 从机地址parameter CLK_FREQ 26d50_000_000 , // 50MHz 的时钟频率parameter …

Ensp dhcp全局地址池(配置命令 + 实例)

使用DHCP的好处&#xff1a;减少管理员的工作量、避免输入错误的可能、避免ip冲突 DHCP报文类型&#xff1a; DHCP DISCOVER:客户端用来寻找DHCP服务器 DHCP OFFER:DHCP服务器用来响应DHCP DISCOVER报文&#xff0c;此报文携带了各种配置信息 DHCP REQUEST:客户端配置请求确…

Python机器学习 – 用最小二乘法实现散点图

Python机器学习 – 用最小二乘法实现散点图 Machine Learning in Python – Implement Scatter Plot with Least Squares By JacksonML 1. 最小二乘法定义 最小二乘法是由A.M.Legendre&#xff08;勒让德&#xff09;先生最早提出的。他在1805年&#xff0c;通过《计算彗星轨…

3. 结构型模式 - 组合模式

亦称&#xff1a; 对象树、Object Tree、Composite 意图 组合模式是一种结构型设计模式&#xff0c; 你可以使用它将对象组合成树状结构&#xff0c; 并且能像使用独立对象一样使用它们 问题 如果应用的核心模型能用树状结构表示&#xff0c; 在应用中使用组合模式才有价值。 …

ISP 状态机轮转和bubble恢复机制学习笔记

1 ISP的中断类型 ISP中断类型 SOF: 一帧图像数据开始传输 EOF: 一帧图像数据传输完成 REG_UPDATE: ISP寄存器更新完成(每个reg group都有独立的这个中断) EPOCH: ISP某一行结尾(默认20)就会产生此中断 BUFFER DONE: 一帧图像数据ISP完全写到DDR了 2 ISP驱动状态机 通过camer…

三菱PLC开关量防抖滤波功能块

开关量防抖滤波功能块梯形图和SCL代码请参考下面文章链接: https://rxxw-control.blog.csdn.net/article/details/134936233https://rxxw-control.blog.csdn.net/article/details/134936233三菱PLC防抖滤波的另一种写法如下 https://rxxw-control.blog.csdn.net/article/det…

用CHAT了解更多知识点

问CHAT&#xff1a;什么是硅基生命和碳基生命&#xff1f; CHAT回复&#xff1a;硅基生命和碳基生命是两种理论性的生物体类型&#xff0c;这些生物体主要是由硅或碳元素以及其他元素构成的。 碳基生命是我们当前所熟知的生命形式。碳元素能够形成稳定且复杂的分子&#xff0c;…

推荐几款非常好用的软件,干货满满!

作为一个工具控&#xff0c;一直在社区索取别人的营养&#xff0c;今天在下将我搜集的一些应用贡献出来&#xff0c;推介十几个我常用的软件。一些是其他人反复推介确实经典&#xff0c;另一些是我偶然发现但经过使用感觉非常好用&#xff0c;一并献上&#xff0c;大家可以根据…

node封装一个图片拼接插件

说在前面 平时我们拼接图片的时候一般都要通过ps或者其他图片处理工具来进行处理合成&#xff0c;这次有个需求就需要进行图片拼接&#xff0c;而且我希望是可以直接使用代码进行拼接&#xff0c;于是就有了这么一个工具包。 插件效果 通过该插件&#xff0c;我们可以将图片进…

Java开发框架和中间件面试题(5)

44.Tomcat一个请求的处理流程&#xff1f; 假设来自客户的请求为&#xff1a; http&#xff1a;//localhost&#xff1a;8080/test/index.jsp请求被发送到本机端口8080&#xff0c;被在那里侦听Copote HTTP/1.1 Connector,然后 1.Connector把该请求交给它所在的Service的Engi…

STM32MP157D-DK1开发板Qt镜像构建

上篇介绍了STM32MP57-DK1开发板官方系统的烧录。那个系统包含Linux系统的基础功能&#xff0c;如果要进行Qt开发&#xff0c;还需要重新构建带有Qt功能的镜像 本篇就来介绍如何构建带有Qt功能的系统镜像&#xff0c;并在开发板中烧录构建的镜像。 1 Distribution包的构建 ST…

[C/C++]数据结构 希尔排序

&#x1f966;前言: 希尔排序也称 “缩小增量排序”&#xff0c;它也是一种插入类排序的方法,在学习希尔排序之前我们首先了解一下直接插入排序. 一: &#x1f6a9;直接插入排序 1.1 &#x1f31f;排序思路 直接插入排序的基本原理是将一条记录插入到已排好的有序表中&#x…