九个视图子类

# 两个视图基类
1.APIView 2.GenericAPIView
APIView: renderer_classes响应格式类 parser_classes请求解析类 跟数据库解耦合
GenericAPIView:queryset数据集 serializer_class序列化类 跟数据库耦合 # 5个视图扩展类 (提供方法)
ListModelMixin --> list --> 查询所有
RetrieveModelMixin --> retrieve --> 查询一个
CreateModelMixin --> create --> 新增一个
UpdateModelMixin --> update --> 修改一个
DestroyModelMixin --> destroy --> 删除一个 # 9个视图子类
继承关系公式: 视图子类 = n * 视图扩展类 + GenericAPIView # 示例:
ListAPIView = ListModelMixin + GenericAPIView
RetrieveAPIView = RetrieveModelMixin + GenericAPIView
CreateAPIView = CreateModelMixin + GenericAPIView
...
RetrieveDestroyAPIView = RetrieveModelMixin + DestroyModelMixin + GenericAPIView
RetrieveUpdateDestroyAPIView = RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin + GenericAPIView '''
总结:9个视图子类都继承GenericAPIView
'''

使用视图子类写五个接口:这里上一节讲过,所以不再赘述。

## 路由
urlpatterns = [
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookView.as_view()),
] # 视图类
class BookView(ListCreateAPIView): # 查询所有,新增一个
queryset = Book.objects.all()
serializer_class = BookSerializer class BookDetailView(RetrieveUpdateDestroyAPIView): # 新增一个,修改一个,删除一个
queryset = Book.objects.all()
serializer_class = BookSerializer

以后可能只希望写某几个接口,而不是全部接口都存在,

可以通过继承不同的视图类实现。

只要查询所有和删除一个,怎么写?

为什么没有Destroy和Updata的组合?

因为必须先查出来,再修改或删除,所以没有这个组合。

继续封装:两个视图类 ---> 一个视图类

问题:

1.有两个get请求对应一个CBV

2.两个路由路径对应一个CBV

视图集

继承ModelViewSet类写五个接口

# 路由
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'})),
] # 视图类
class BookView(ModelViewSet): # 查询所有,新增一个
queryset = Book.objects.all()
serializer_class = BookSerializer

查看ModelViewSet内部继承关系:

从注释也可以看出来他继承了 5个视图扩展类,也就是说ModelViewSet内部具备所有的"动作",也就是例如:

create()list()update()retrieve()destroy()这些方法

但是我们请求来了,还是会调用视图类中的get()post()put()delete()这些方法呀。

比如一个扩展子类:ListAPIView

他的内部就是写了get方法,我们get请求来了之后,就会调用这个方法,然后再去调用父类的list方法。

ModelViewSet内部居然没有写,这是怎么回事?

这是因为ModelViewSet继承的最后一个类GenericViewSet,这是一个魔法类,他重写了as_view。

我们直接发个请求运行一下。

会发现如下报错:

可以得知,一旦继承ModelViewSet,路由层的写法就变了!

现在需要这样写:

这样写的意思是:

  • 对于books/这个路由:

    get请求 --执行--> list方法

    post请求 --执行--> create方法

  • 对于books/<int:pk>/这个路由:

    get请求 --执行--> retrieve方法

    put请求 --执行--> updata方法

    delete请求 --执行--> destroy方法

先记住这个格式,知道怎么用,后续源码分析再详细了解。

继承 ReadOnlyModelView编写2个只读接口

# 路由
urlpatterns = [
path('books/', views.BookView.as_view({'get': 'list'})),
path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve'})),
] # 视图类
class BookView(ReadOnlyModelViewSet): # 查询所有,新增一个
queryset = Book.objects.all()
serializer_class = BookSerializer

查看 readonlymodelview内部继承关系:

这个类中只有list方法和retrieve方法。他同样继承了魔法类。

所以继承这个类就只能写两个只读接口:查询所有、查询一个

ViewSetMixin源码分析

查看GenericViewSet继承关系:

ViewSetMixin是个魔法类,重写了as_view:

查找as_view方法

路由写法为什么变了?

导致路由写法变了的原因是: ViewSetMixin

当请求来了之后,会执行ViewSetMixin类中的as_view方法的返回值。

# 请求来了,路由匹配成功---》get请求,匹配成功books,会执行  views.BookView.as_view({'get': 'list', 'post': 'create'})()------>读as_view【这个as_view是ViewSetMixin的as_view】

从路由层开始分析,根据继承属性一个一个找as_view方法(从左往右)

ListModelMixinRetrieveModelMixinCreateModelMixinUpdateModelMixin DestroyModelMixin这些方法中都没有as_view。

所以会进入到GenericViewSet:

GenericViewSet的第一个父类是ViewSetMixin。

所以会先执行ViewSetMixin的as_view():

@classonlymethod
def as_view(cls, actions=None, **initkwargs):
# 如果没有传actions,直接抛异常,路由写法变了后,as_view中不传字典,直接报错
if not actions:
raise TypeError("The `actions` argument must be provided when "
"calling `.as_view()` on a ViewSet. For example "
"`.as_view({'get': 'list'})`")
# 。。。。其他代码不用看
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if 'get' in actions and 'head' not in actions:
actions['head'] = actions['get']
self.action_map = actions
for method, action in actions.items():
handler = getattr(self, action)
setattr(self, method, handler) return self.dispatch(request, *args, **kwargs)
# 去除了csrf校验
return csrf_exempt(view)

如果不给actions传参数,直接抛出异常。

也就是不给as_view()传字典,就会抛出异常。

as_view执行完后会返回内层函数view:(这里执行的view是去除了csrf校验的)

# 路由匹配成功执行views.BookView.as_view({'get': 'list', 'post': 'create'})()----》本质执
行ViewSetMixin----》as_view----》内的view()---》代码贴过来
def view(request, *args, **kwargs):
#actions 是传入的字典--->{'get': 'list', 'post': 'create'}
self.action_map = actions
# 第一次循环:method:get,action:list
# 第一次循环:method:post,action:create
for method, action in actions.items():
# 反射:去视图类中反射,action对应的方法,action第一次是list,去视图类中反射list方法
# handler就是视图类中的list方法
handler = getattr(self, action)
# 反射修改:把method:get请求方法,handler:list
# 视图类的对象的get方法,变成了list
setattr(self, method, handler) return self.dispatch(request, *args, **kwargs) #dispatch是APIView的 # 关于这里self.dipatch的说明
self.dipatch是APIView的dispatch
'''
self.dipatch --进行--> 封装新request, 执行三大认证 --调用--> django view的dispatch
'''
# 关于反射的总结
反射得到的是我们继承的List create方法
反射修改对象的属性 比如将get方法修改为存放list方法
最后的dispatch作用是获取你写的CBV类中的get方法(此时get方法 --> list方法)。
魔法类可以修改对象中的属性所指向的方法。 # 关于整体的总结:
-1 只要继承ViewSetMixin的视图类,路由写法就变了(重写了as_veiw)
-2 变成需要需要传入字典映射方法:{'get': 'list', 'post': 'create'}
-只要传入actions,以后访问get就是访问list,访问post,就是访问create
-3 其他执行跟之前一样
-4 以后视图类类中的方法名,可以任意命名,只要在路由中做好映射即可【重要】

setattr修改对象的属性

实际上ModelViewSet中根本没有get方法,我们通过setattr给CBV的对象新增了一个get属性,里面存放的就是list方法。

而这个list方法又是通过反射在CBV的父类获取到的。所以就产生了这么神奇的效果。

我们也可以在自己的CBV中重写list方法,这样getattr获取到的就是我们重写的list方法,然后get请求来了之后,也会执行我们重写的这个list。重写list之后,建议使用super方法调用一下父类的list,这样就可以在父类list的基础上,新增一些功能。

# 示例:
def token_auth(func):
def inner(self, request, *args, **kwargs):
token = request.query_params.get('token')
token_exist = UserToken.objects.filter(token=token)
if token_exist:
res = func(self, request, *args, **kwargs)
return res
else:
return Response({'code': 100, 'msg': '请先登录'}) return inner class BookView(ModelViewSet): # 针对 获取一个 修改一个 删除一个 接口添加token验证
queryset = Book.objects
serializer_class = BookSerializer @token_auth
def retrieve(self, request, *args, **kwargs):
res = super().retrieve(request, *args, **kwargs)
return res @token_auth
def update(self, request, *args, **kwargs):
res = super().update(request, *args, **kwargs)
return res @token_auth
def destroy(self, request, *args, **kwargs):
res = super().update(request, *args, **kwargs)
return res

from rest_framework.viewsets包下的类


# from rest_framework.viewsets下有这几个类: ViewSetMixin:魔法类,重写了as_view,只要继承他,以后路由写法变成了映射方法
ModelViewSet: 5个视图扩展类 + ViewSetMixin(魔法类) + GenericAPIView
ReadOnlyModelViewSet: 2个视图扩展类 + ViewSetMixin(魔法类) + GenericAPIView 只读的两个
ViewSet:ViewSetMixin(魔法类) + APIView
GenericViewSet:ViewSetMixin(魔法类) + GenericAPIView # 重点
以后,你想继承APIView,但是想变路由写法【视图类中方法名任意命名】,要继承ViewSet
以后,你想继承GenericAPIView,但是想变路由写法【视图类中方法名任意命名】,要继承GenericViewSet # 总结
只要想变路由,就要继承ViewSetMixin,但是ViewSetMixin不是CBV视图类,他没有list,create等方法,所以要配合APIView, GenericAPIView一起使用,所以会出现ViewSet,GenerucViewSet,帮助我们继承好了。
ViewSet: ViewSetMixin(魔法类) + APIView
GenericViewSet:ViewSetMixin(魔法类) + GenericAPIView

视图层大总结

# 1. 两个视图基类
-APIView,GenericAPIView
# 2. 5个视图扩展类,不是视图类,必须配合GenericAPIView # 3. 9个视图子类,是视图类,只需要继承其中某一个即可 # 4. 视图集
-ModelViewSet:路由写法变了,只需要写两行,5个接口都有了
-ReadOnlyModelViewSet:路由写法变了,只需要写两行,2个只读接口都有了
-ViewSetMixin:不是视图类,魔法,重写了as_view,路由写法变了,变成映射了
views.BookView.as_view({'get': 'list', 'post': 'create'})
-ViewSet:ViewSetMixin+ APIView
-GenericViewSet:ViewSetMixin+ GenericAPIView # 举例子:发送短信接口,视图类叫SendView,方法叫send_sms,路由配置变了
get--->send_sms
class SendView(ViewSet):
def send_sms(self,request):

任意命名视图类的方法

在视图类写的方法可以任意命名,只要在路由层的字典写好映射关系就行。

只要想变路由,就要继承ViewSetMixin,但是ViewSetMixin不是CBV视图类,他没有list,create等方法,所以要配合APIView,GenericAPIView一起使用,所以会出现ViewSet,GenerucViewSet,帮助我们继承好了。

如何选择视图类

  • 为什么要使用APIview?

    对于发送短信的接口,

    其不跟数据库打交道:继承ViewSet

    ViewSet = 魔法类 + APIView

    因为APIView不需要配置queryset和序列化类

    继承GenericViewSet会查数据库,这是一种资源的浪费。

    所以跟数据库打交道:继承GenericViewSet

    GenericViewSet = 魔法类 + GenericAPIview

  • 有没有推荐的视图类组合?

    9个视图子类 + 魔法类

    因为通常我们对一个数据库资源比如:user

    对于这些数据资源,我们不一定会提供全部接口,很可能只会写其中的几个接口。

路由系统

路由写法的三种情况

# drf 由于继承ViewSetMinxin类,路由写法变了
-原生+drf,以后的路由写法,可能会有如下情况(三种情况)
-path('books/', views.BookView.as_view()
# 原生django写法
-path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'}))
# 魔法类路由写法
-自动生成 ---> 还有扩展

路由类的使用

使用路由类是为了自动生成路由。

# drf提供了两个路由类,继承ModelViewSet后,路由可以自动生成

# 使用步骤:
# 第一步:导入路由类
# 第二步,实例化得到对象(两个类,一般使用SimpleRouter)
# 第三步:注册:router.register('books', views.BookView, 'books')
# 第四步:在urlpatterns中注册,两种方式
-urlpatterns += router.urls
-include:path('/api/v1/', include(router.urls)) 方式多一些 # 底层实现:自动生成路由就
-本质是自动做映射,能够自动成的前提是,视图类中要有 5个方法的某要给或多个
get--->list
get---->retrieve
put---->update
post---->create
delete---->destory
-ModelViewSet,ReadOnlyModelViewSet可以自动生成 -9个试图子类+配合ViewSetMixin 才可以自动生成
-GenericAPIView+5个试图扩展类+配合ViewSetMixin 才能自动生成

使用步骤

第一步:导入路由类 使用simplerouter 就生成两个路由 使用DefaultRouter -->生成的路由更多

第二步:实例化得到对象。

第三步:注册路由。路径和视图类建立关系 有几个视图类就要写几次

第四步:在urlpatterns注册

也就是将生成好的路由,添加到urlpatterns列表。

使用SimpleRouter(常用)

from rest_framework.routers import SimpleRouter

router =  SimpleRouter()
router.register('books', views.BookView, 'books') urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls

关于router.register:

第一个参数:具体路由地址 (会自动帮我们加斜杠,这里不需要跟以前一样添加)

第二个参数:该路由地址对应的视图类

第三个参数:相当于是一个路由别名

来自官方文档:

register() 方法有两个强制参数:

  • prefix - 用于此组路由的URL前缀。
  • viewset` - 处理请求的viewset类。

还可以指定一个附加参数(可选):

  • base_name - 用于创建的URL名称的基本名称。如果不设置该参数,将根据视图集的queryset属性(如果有)来自动生成基本名称。
  • 注意,如果视图集不包括queryset属性,那么在注册视图集时必须设置base_name

SimpleRouter会生成两个接口:

可以发现一个是 books/另一个是books/pk/

使用DefaultRouter

DefaultRouter比SimpleRouter多写了一些接口:

还包括一个默认返回所有列表视图的超链接的API根视图。

访问根,可以看到有哪些地址:

注册路由的两种方式

直接添加到urlpatterns列表

from rest_framework.routers import SimpleRouter, DefaultRouter

router = DefaultRouter()
router.register('books', views.BookView, 'books')
# router.register('api/v1/books', views.BookView, 'books') urlpatterns = [
path('admin/', admin.site.urls),
] urlpatterns += router.urls # 在这里添加 # router.urls也是一个列表:
[<URLPattern '^books/$' [name='books-list']>, <URLPattern '^books/(?P<pk>[^/.]+)/$' [name='books-detail']>]

使用路由分发include

from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('books', views.BookView, 'books') urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include(router.urls))
]

自动生成路由底层实现

# 自动生成路由底层实现
-本质是自动做映射,能够自动生成的前提是,视图类中要有 5个方法的某个或多个
get--->list
get---->retrieve
put---->update
post---->create
delete---->destory - ModelViewSet,ReadOnlyModelViewSet 可以自动生成
- 9个试图子类 + 配合ViewSetMixin 可以自动生成
- GenericAPIView + 5个试图扩展类+配合ViewSetMixin 可以自动生成

什么时候可以自动生成路由?

前提: 有list,create...等方法 有ViewSetMixin魔法类

自动生成路由使用的多,ModelViewSet用的不多,因为我们通常使用一个或者两个接口 。

所以如下这个组合用的多:

9个试图子类 + 配合ViewSetMixin

9个视图子类提供listcreate...方法 ViewSetMixin反射进行对象属性替换,使得get对应list 。

action装饰器

使用装饰器会将被装饰的方法的名字添加在原路由的后面,生成一个新路由:

原路由:send/

装饰器新增的路由:send/方法名/

# action 写在视图类的方法上,可以自动生成路由

# 使用步骤
- 1 写在视图类方法上
class SendView(ViewSet):
# methods指定请求方法,可以传多个
# detail:只能传True和False
-False,不带id的路径:send/send_sms/
-True,带id的路径:send/2/send_sms/
# url_path:生成send后路径的名字,默认以方法名命名
# url_name:别名,反向解析使用,了解即可
@action(methods=['POST'], detail=False)
def send_sms(self, request): # 以后看到的drf路由写法
后期,都是自动生成,一般不在urlpatterns 加入路由了 # 补充:
-1 不同请求方式可以使用不同序列化类
-2 不同action使用不同序列化类
class SendView(GenericViewSet):
queryset = None
serializer_class = '序列化类' def get_serializer(self, *args, **kwargs):
if self.action=='lqz':
return '某个序列化类'
else:
return '另一个序列化列'
@action(methods=['GET'], detail=True)
def send_sms(self, request,pk):
print(pk)
# 手机号,从哪去,假设get请求,携带了参数
phone = request.query_params.get('phone')
print('发送成功,%s' % phone)
return Response({'code': 100, 'msg': '发送成功'}) @action(methods=['GET'], detail=True)
def lqz(self,request): # get
# 序列化类
pass @action(methods=['GET'], detail=True)
def login(self,request): # get
# 序列化类
pass

无法自动生成的路由

我们知道路由自动生成,是实现了请求(get)和类中方法(list)的对应。

如果我们在类中写listcreate,... ,updata之外的方法呢?

还能自动生成这些方法的路由吗?

示例:

get携带参数,参数是手机号

路由怎么写?

如果这样写,那就相当于get请求映射send_sms方法而不是list方法。

自动生成路由,只能映射到list,create...,但是我们需要执行send_sms,并且区分开原来的list方法,所以需要加drf提供的装饰器:

加上这个装饰之后,会新增一个路由send/send_sms/

这样就可以对这个新增的路由发送请求了。

不同action使用不同序列化类

class SendView(GenericViewSet):
queryset = None
serializer_class = '序列化类' def get_serializer(self, *args, **kwargs):
if self.action=='lqz':
return '某个序列化类'
else:
return '另一个序列化列'
@action(methods=['GET'], detail=True)
def send_sms(self, request,pk):
print(pk)
# 手机号,从哪去,假设get请求,携带了参数
phone = request.query_params.get('phone')
print('发送成功,%s' % phone)
return Response({'code': 100, 'msg': '发送成功'}) @action(methods=['GET'], detail=True)
def lqz(self,request): # get
# 序列化类
pass @action(methods=['GET'], detail=True)
def login(self,request): # get
# 序列化类
pass

如何实现不同的方法,使用不同的序列化类?

用action产生的路径来判断不同的get请求。

我怎么知道self里面有个action,在什么时候放进去的?

在ViewSetMixin:

自动生成路由时才会有action属性.

action_map是as_view传入的字典。

查看self.action:

认证组件前戏

登录接口

# 访问某个接口,需要登陆后才能访问

# 第一步:写个登录功能,用户表
-User表
-UserToken表:存储用户登录状态 [这个表可以没有,如果没有,把字段直接写在User表上也可以]

随机字符串可以放在user表,也可以放在usertoken表里。

建表:

用户删掉掉了之后,用户token没有存在的必要。所以可以使用级联删除。

虽然UserToken中没有外键,但是UserToken还是可以进行反向查询,其生成的对象中有一个user属性。(反向查询表名小写)

登录接口:

登录接口是不需要使用序列化类的。

使用uuid模块生成随机字符串。

关于传给前端的随机字符串,最好不要用时间戳。

时间戳怎么重复?不同机器可能出现同一时间戳,及不同机器同一时间登录。

updata_or_create方法:

根据user去查,如果能查到,就把default里面的token给放进去。也就是如果有token就更新,如果没有就创建。

登录接口:

#### 表模型

class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32) class UserToken(models.Model): # 跟User是一对一
token = models.CharField(max_length=32)
user = models.OneToOneField(to='User', on_delete=models.CASCADE, null=True)
# user :反向,表名小写,所有有user字段 ### 路由
router.register('user', views.UserView, 'user') # /api/v1/user/login post 请求 # 视图类
#### 登录接口 自动生成路由+由于登录功能,不用序列化,继承ViewSet
from .models import User, UserToken
import uuid class UserView(ViewSet):
@action(methods=['POST'], detail=False)
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username, password=password).first()
if user:
# 用户存在,登录成功
# 生成一个随机字符串--uuid
token = str(uuid.uuid4()) # 生成一个永不重复的随机字符串
# 在userToken表中存储一下:1 从来没有登录过,插入一条, 2 登录过,修改记录
# 如果有就修改,如果没有就新增 (if 自己写)
# kwargs 传入的东西查找,能找到,使用defaults的更新,否则新增一条
UserToken.objects.update_or_create(user=user, defaults={'token': token})
return Response({'code': '100', 'msg': '登录成功', 'token': token})
else:
return Response({'code': '101', 'msg': '用户名或密码错误'})

【Django drf】视图层大总结 ViewSetMixin源码分析 路由系统 action装饰器的更多相关文章

  1. springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)

    在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...

  2. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  3. Tomcat源码分析(类加载与类加载器)

    Tomcat的挑战 Tomcat上可以部署多个项目 Tomcat的一般部署,可以通过多种方式启动一个Tomcat部署多个项目,那么Tomcat在设计时会遇到什么挑战呢? Tomcat运行时需要加载哪些 ...

  4. drf框架,restful接口规范,源码分析

    复习 """ 1.vue如果控制html 在html中设置挂载点.导入vue.js环境.创建Vue对象与挂载点绑定 2.vue是渐进式js框架 3.vue指令 {{ }} ...

  5. Django框架(十八)—— CBV源码分析、restful规范、restframework框架

    目录 CBV源码分析.restful规范.restframework框架 一.CBV源码分析 1.url层的使用CBV 2.as_view方法 3.view方法 4.dispatch方法(可以在视图层 ...

  6. drf的基本使用、APIView源码分析和CBV源码拓展

    cbv源码拓展 扩展,如果我在Book视图类中重写dispatch方法 -可以实现,在get,post方法执行之前或者之后执行代码,完成类似装饰器的效果 def dispatch(self, requ ...

  7. Django 之 restframework 版本控制的使用以及源码分析

    Django rest_framework 之 版本控制 一.何为版本控制: ​ 用于版本的控制 二.内置的版本控制类: from rest_framework.versioning import Q ...

  8. SpringMVC视图机制详解[附带源码分析]

    目录 前言 重要接口和类介绍 源码分析 编码自定义的ViewResolver 总结 参考资料 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门bl ...

  9. 【lwip】07-链路层收发以太网数据帧源码分析

    目录 前言 7.1 链路层概述 7.2 MAC地址的基本概念 7.3 以太网帧结构 7.4 以太网帧结构 7.5 以太网帧报文数据结构 7.6 发送以太网数据帧 7.7 接收以太网数据帧 7.8 虚拟 ...

  10. 精尽Spring Boot源码分析 - 日志系统

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

随机推荐

  1. .NET性能优化-是时候换个序列化协议了

    计算机单机性能一直受到摩尔定律的约束,随着移动互联网的兴趣,单机性能不足的瓶颈越来越明显,制约着整个行业的发展.不过我们虽然不能无止境的纵向扩容系统,但是我们可以分布式.横向的扩容系统,这听起来非常的 ...

  2. <二>掌握构造函数和析构函数

    构造函数 和类名相同,可以带参数,参数可以有多个 构造函数执行完成后,内存开辟完成,同时可以完成初始化工作. 析构函数 ~Test(); 析构函数可以自己调用,析构函数调用后,对象不存在了.自己调了析 ...

  3. MessagePack 和System.Text.Json 序列号 反序列化对比

    本博客将测试MessagePack 和System.Text.Json 序列号 反序列化性能 项目文件: Program.cs代码: using BenchmarkDotNet.Running; us ...

  4. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(34)-Fiddler如何抓取微信小程序的包-上篇

    1.简介 有些小伙伴或者是童鞋们说小程序抓不到包,该怎么办了???其实苹果手机如果按照宏哥前边的抓取APP包的设置方式设置好了,应该可以轻松就抓到包了.那么安卓手机小程序就比较困难,不是那么友好了.所 ...

  5. 2022春每日一题:Day 23

    题目:Piotr's Ants 蚂蚁转头走,其实可以看做他们交换灵魂后接着往前走,同样发现,既然他们的速度相同,那么在数轴上相对位置不会改变(碰面会改变方向),那就好办了. 先把初始状态排序,id都记 ...

  6. 5.django-模型ORM

    Django中内嵌了ORM框架,不需要直接编写SQL语句进行数据库的操作,通过定义模型类来完成对数据库中表的操作 O:Object,也就是类对象的意思 R:Relation,关系数据库中表的意思 M: ...

  7. kubernetes笔记-3-快速入门

    一.增删改查 root@master:~# kubectl run ninig-deploy --image=nginx:1.14-alpine --port=80 --replicas=1 --dr ...

  8. linux sublime-text ctrl+shift+b 快捷键失效问题解决

    解决办法 由于fcitx拦截了这个ctrl+shift+b 这个快捷键,所以取消即可 点击全局配置里面高级选项,然后找到ctrl+shift+b这个快捷键,点击后,按esc就可以将快捷键设置为空,不过 ...

  9. (四) 一文搞懂 JMM - 内存模型

    4.JMM - 内存模型 1.JMM内存模型 JMM与happen-before 1.可见性问题产生原因 下图为x86架构下CPU缓存的布局,即在一个CPU 4核下,L1.L2.L3三级缓存与主内存的 ...

  10. MIsc writeup

    1. 杂项 图片里面有什么 ,附件为一张图片 通过Binwalk查看发现有压缩包,通过foremost分离一下. 打开输出文件,发现里面有两个图片. 00000000.png是原图,00000722. ...