python-restful-02-组件(序列化\认证)
参考: rest-framework框架基础组件, 基于Token的WEB后台认证机制,rest-framework之序列化组件
restful组件-1
一、序列化
对比:自己写的 for循环处理 (相对麻烦)django自带序列化工具 (不可控, 字段太多, 会造成网络拥堵问题)restful工具可控,但配置比较多, 后续会轻松些
1.1、django自带serializers
- 使用说明
# 1、导入 from django.core import serializers
# 2、实例化 res = serializers.serialize('json', queryset)
- 例子
from app01.models import Authers
from django.core import serializers
from rest_framework.views import APIView
from django.http.response import JsonResponseclass Mydjangoser(APIView):def get(self, reuqest):auther = Authers.objects.all()ser = serializers.serialize('json', auther)# safe=False 如果不设置这个 当字典中还有列表时返回就会报错return JsonResponse(ser, safe=False)# 访问,因为序列化已经是字符串了,所以看的结果就是ascii
"[{\"model\": \"app01.authers\", \"pk\": 1, \"fields\": {\"name\": \"xiong\", \"pwd\": \"12\"}}, {\"model\": \"app01.authers\", \"pk\": 2, \"fields\": {\"name\": \"we\", \"pwd\": \"321\"}}]"# 可以直接返回 HttpResponse return HttpResponse(ser)
[{"model": "app01.authers", "pk": 1, "fields": {"name": "xiong", "pwd": "12"}}, {"model": "app01.authers", "pk": 2,
"fields": {"name": "we", "pwd": "321"}}]# 字典中的字段无用的就太多了会给网络带来拥堵
1.2、drf的Serializer
- 使用说明
# 1、先在 setting.py中注册 restful
# 2、导入 from rest_framework import serializers
# 3、引用 res = AutherSerializer(instance=queryset对象, many=True)
# 4、返回数据 res.data
继承serializers.Serializers
# 想序列化哪一个模型就将字段序列化 class AutherSerializer(serializers.Serializer):name = serializers.CharField()age = serializers.CharField()
类使用
class Mydjangoser(APIView):def get(self, reuqest):auther = Authers.objects.all()# 初始化方法 def __init__(self, instance=None, data=empty, **kwargs)# many 如果传true说明queryset对象中有多条, kwargs.pop('many', None)# many 传false说明就只有一条字典res = AutherSerializer(instance=auther, many=True)# res.data 获取序列化的数据return JsonResponse(res.data, safe=False)# 返回结果 [{"name": "xiong","pwd": "12"},{"name": "we","pwd": "321"}]
1.2.1、Serializer-source
# 模型: class Userinfo(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=32)pwd = models.CharField(max_length=64)userdetail = models.OneToOneField(to="Userdetail", to_field="id", on_delete=models.CASCADE)class Userdetail(models.Model):id = models.AutoField(primary_key=True)phone = models.IntegerField(max_length=13)email = models.EmailField()# 视图class MyUser(APIView):def get(self, request, *args, **kwargs):user_list = Userinfo.objects.all()users = UserSerializers(instance=user_list, many=True)return JsonResponse(users.data, safe=False)
正常
# 序列化 from rest_framework import serializersclass UserSerializers(serializers.Serializer):name = serializers.CharField()pwd = serializers.CharField()userdetail = serializers.CharField()[{"name": "xiong","pwd": "123","userdetail": "Userdetail object (1)"},{"name": "hello","pwd": "321","userdetail": "Userdetail object (2)"}]
**source属性-1 修改名称 **
# 将name修改为hello class UserSerializers(serializers.Serializer):hello = serializers.CharField(source="name")pwd = serializers.CharField()userdetail = serializers.CharField()[{"hello": "xiong","pwd": "123","userdetail": "Userdetail object (1)"},{"hello": "hello","pwd": "321","userdetail": "Userdetail object (2)"}]
source属性-2 一对一
class UserSerializers(serializers.Serializer):hello = serializers.CharField(source="name")pwd = serializers.CharField()userdetail = serializers.CharField(source="userdetail.email")[{"hello": "xiong","pwd": "123","userdetail": "22@qq.com"},{"hello": "hello","pwd": "321","userdetail": "33@qq.com"}]
1.2.2、SerializerMethodField
- 正常写法
class UserSerializers(serializers.Serializer):hello = serializers.CharField(source="name")pwd = serializers.CharField()userdetail = serializers.SerializerMethodField()# 这里的obj 其实就是 userinfo 的对象def get_userdetail(self, obj):return obj.userdetail.email[{"hello": "xiong","pwd": "123","userdetail": "22@qq.com"},{"hello": "hello","pwd": "321","userdetail": "33@qq.com"}]
- 返回关连表的全部, 像这样就需要一个一个的拼接比较麻烦
class UserSerializers(serializers.Serializer):hello = serializers.CharField(source="name")pwd = serializers.CharField()userdetail = serializers.SerializerMethodField()def get_userdetail(self, obj):# obj就是一个一个的对象, 类似于已经 .first了return {"email": obj.userdetail.email, "phone": obj.userdetail.phone}
- 多表关连 - 写法1
# 单表没有.all属性,切记切记,
class UserSerializers(serializers.Serializer):name = serializers.CharField()user = serializers.CharField()publish = serializers.SerializerMethodField()def get_publish(self, obj):xx = obj.publish.all()return [{"name": x.name} for x in xx]
- 多表关连- 写法2
class PublishSerializers(serializers.Serializer):name = serializers.CharField()class UserSerializers(serializers.Serializer):name = serializers.CharField()user = serializers.CharField()publish = serializers.SerializerMethodField()def get_publish(self, obj):xx = obj.publish.all()xy = PublishSerializers(instance=xx, many=True)return xy.data
1.2.3、ModelSerializer
- 获取全部属性的方法
from app01.models import *
from rest_framework import serializersclass BookSerializer(serializers.ModelSerializer):# 元属性, 固定格式如下class Meta:model = Bookfields = "__all__"# 返回结果为 [{"id": 1, "name": "linux", "user": 1, "publish": [ 1 ]},.....]
- 只显示某个值(类型于白名单)
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookfields = ["name", "user"]
# 返回结果: [{"name": "linux", "user": 1},.....]
- 不显示某些值(黑名单)
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookexclude = ["id"]user = serializers.CharField(source="user.name")
# 返回结果为 [{"name": "linux", "user": 1, "publish": [ 1 ]},.....]
depth 深度
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookexclude = ["id"]depth = 3 # 官方建议是10层,但如果表的字段很多会造成性能问题,建议2-3层
配合source使用
class BookSerializer(serializers.ModelSerializer):class Meta:model = Book# fields = "__all__"fields = ["name", "user"]user = serializers.CharField(source="user.name") # 返回结果: [{"name": "linux", "user": "xiong"},.....]
配合 ModelSerializer
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookexclude = ["id"]user = serializers.CharField(source="user.name")publish = serializers.SerializerMethodField()def get_publish(self, publish_obj):publish_all = publish_obj.publish.all()print(publish_all) # <QuerySet [<Publish: Publish object (1)>]>return PublishSerializers(publish_all, many=True).data# 返回结果[{"user": "xiong", "publish": [{"name": " 上海出版"}],"name": "linux"},...]
1.2.4、HyperlinkedIdentityField
鸡肋,并没有什么用,URL前台拼就行
序列化
# class BookSerializer(serializers.Serializer): # name = serializers.CharField() # publish = serializers.HyperlinkedIdentityField(view_name="publish", # lookup_url_kwarg="pk", # lookup_field="publish")class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookexclude = ["id"]publish = serializers.HyperlinkedIdentityField(view_name="publish",lookup_url_kwarg="pk",lookup_field="pk")# view_name: 视图别名, lookup_url_kwarg: url后传的参数, # lookup_field: 本表的字段ID # lookup_url_kwarg 相当于是key, lookup_field相当是value
路由函数
from django.urls import re_path
from app01.views import *urlpatterns = [re_path("publish/(?P<pk>\d+)", Mypublish.as_view(), name="publish"),
]
视图
class Mypublish(APIView):def get(self, request, pk):response = {"status": 1000, "msg": None}res = Publish.objects.filter(pk=pk).first()if res:res_ser = PublishSerializers(instance=res, many=False)response["msg"] = res_ser.dataelse:response["status"] = 1002response["msg"] = "没有这个字段"return JsonResponse(response, safe=False)
error_messages
# 错误字段显示为中文name = serializers.CharField(error_messages={"required": "必填字段"})
1.3、反序列化
保存和修改, 必须是继承了ModelSerializer的类才能使用
- 保存
class Mybook(APIView):def get(self, request, *args, **kwargs):book_list = Book.objects.all()books = BookSerializer(instance=book_list, many=True, context={'request': request})return JsonResponse(books.data, safe=False)def post(self, request, *args, **kwargs):response = {"status": 1000, "msg": None}data = request.data# 数据检验ret = BookSerializer(data=data, many=False)# 检验数据是否正常if ret.is_valid():# 如果 是多对多表,这里需要做一下检验,比如是不是列表,是否为空xx = ret.save() # 保存类型: <class 'app01.models.Book'>publists = data.get("publish")if publists:if isinstance(publists, list):for p_num in publists:p = Publish.objects.filter(pk=p_num).first()xx.publish.add(p)else:p = Publish.objects.filter(pk=data.get("publish")).first()xx.publish.add(p)response["msg"] = "添加成功"else:response["status"] = 1002response["msg"] = "没有这个字段"return JsonResponse(response, safe=False)
修改
class Mybookdetail(APIView):def get(self, request, pk, *args, **kwargs):response = {"status": 1000, "msg": None}book_detail = Book.objects.filter(pk=pk).first()if book_detail:ret = BookSerializer(instance=book_detail, many=False)response["msg"] = ret.datareturn JsonResponse(response, safe=False)def put(self, request, pk, *args, **kwargs):response = {"status": 1000, "msg": None}book_detail = Book.objects.filter(pk=pk).first()if book_detail:# BookSerializer(data=book_detail, )ret = BookSerializer(data=request.data, instance=book_detail)data = request.data# ==================== 与添加一样# 检验数据是否正常if ret.is_valid():# 如果 是多对多表,这里需要做一下检验,比如是不是列表,是否为空xx = ret.save() # 保存类型: <class 'app01.models.Book'>publists = data.get("publish")if publists:if isinstance(publists, list):for p_num in publists:p = Publish.objects.filter(pk=p_num).first()xx.publish.add(p)else:p = Publish.objects.filter(pk=publists).first()xx.publish.add(p)response["msg"] = "添加成功"else:response["status"] = 1001response["msg"] = ret.errorsreturn JsonResponse(response, safe=False)
总结
# 添加: 获取数据并检验,最后给它保存ret = BookSerializer(data=data, many=False)if ret.is_valid(): ret.save()# 修改: 与添加不同的是, 获取数据前,需要先前修改的数据取出,然后在做检验最后保存ret = BookSerializer(data=request.data, instance=book_detail)if ret.is_valid(): ret.save()
1.4、钩子函数
1.4.1、源码分析
if ret.is_valid(): ret.save()
# 直接从属性方法这进入到检验中, 需要注意的是 self.的都需要从第一级重新开始找, MRO
- 检验方法is_valid
def is_valid(self, raise_exception=False):if not hasattr(self, '_validated_data'):try:# 这里是获取到全局的属性值self._validated_data = self.run_validation(self.initial_data).....if self._errors and raise_exception:raise ValidationError(self.errors)return not bool(self._errors)
self.run_validation
self.run_validation, 已知self是 BookSerializer,从父属性开始找# 找到 Serializer/run_validationdef run_validation(self, data=empty):# 这里返回的是每个参数的值value = self.to_internal_value(data)try:self.run_validators(value)value = self.validate(value)assert value is not None, '.validate() should return the validated data'except (ValidationError, DjangoValidationError) as exc:raise ValidationError(detail=as_serializer_error(exc))return value
value = self.validate(value), 全局钩子函数
# value = self.validate(value), 获取到这个属性,就是全局钩子函数,我们可以使用派生修改它def validate(self, attrs):return attrs # 返回的结果就是每个序列化的值, 全局钩子函数
self.to_internal_value(data)
# 这里返回的是每个参数的值value = self.to_internal_value(data)# 局部钩子函数def to_internal_value(self, data):# filds 就是 user = serializers.CharField, 将其变为字典for field in fields:# 'validate_' + field.field_name 拼接的属性,这里就是局部的钩子函数# 如果没有就是 none, 使用的restful自带的检验validate_method = getattr(self, 'validate_' + field.field_name, None)primitive_value = field.get_value(data)....return ret
1.4.2、钩子
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookexclude = ["id"]# 局部钩子def validate_name(self, data):if len(data) >=10:raise ValidationError("长度不能大于10")return data# 错误显示: "name": [ "长度不能大于10" ]# 全局钩子def validate(self, data):print("全局钩子")return data # 必须要返回data# assert value is not None, '.validate() should return the validated data'
二、认证
2.1、认证源码分析
从url开始
path("atest/", Atest.as_view()),
进入到 ApiView/as_view()函数中
@classmethoddef as_view(cls, **initkwargs):# 继承了父类的 as_view方法view = super().as_view(**initkwargs)view.cls = clsview.initkwargs = initkwargsreturn csrf_exempt(view)
此时是父类的 View/as_view
@classonlymethoddef as_view(cls, **initkwargs):......def view(request, *args, **kwargs):.....# 注意,这里的self是 函数也就是Atest, 又从 ApiView重新开始找return self.dispatch(request, *args, **kwargs)
进入到 ApiView/dispatch中
def dispatch(self, request, *args, **kwargs):self.args = argsself.kwargs = kwargs# 在这里重新封装了 request,进入查看request = self.initialize_request(request, *args, **kwargs)self.request = requestself.headers = self.default_response_headers # deprecate?try:self.initial(request, *args, **kwargs)......except Exception as exc:response = self.handle_exception(exc)self.response = self.finalize_response(request, response, *args, **kwargs)return self.response
request = self.initialize_request(request, *args, **kwargs)
def initialize_request(self, request, *args, **kwargs):"""Returns the initial request object."""parser_context = self.get_parser_context(request)# 返回的是重新封装好的Requestreturn Request(request,parsers=self.get_parsers(),# authenticators, 认证模块authenticators=self.get_authenticators(),negotiator=self.get_content_negotiator(),parser_context=parser_context)
authenticators=self.get_authenticators(),
# 也就是说 authenticators 返回的是一个个的列表套对象 [对象内存地址1,2,3 ]def get_authenticators(self):return [auth() for auth in self.authentication_classes]# 默认的配置文件authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
self.initial(request, *args, **kwargs)
def initial(self, request, *args, **kwargs):"""Runs anything that needs to occur prior to calling the method handler."""self.format_kwarg = self.get_format_suffix(**kwargs)# Perform content negotiation and store the accepted info on the requestneg = self.perform_content_negotiation(request)request.accepted_renderer, request.accepted_media_type = neg# Determine the API version, if versioning is in use.version, scheme = self.determine_version(request, *args, **kwargs)request.version, request.versioning_scheme = version, scheme# Ensure that the incoming request is permittedself.perform_authentication(request)self.check_permissions(request)self.check_throttles(request)
self.perform_authentication(request)
def perform_authentication(self, request):# 最终返回的就是一个request.userrequest.user
继续往下看 request.user属性
from rest_framework.request import Request
# 进入Request中找着 user方法@propertydef user(self):if not hasattr(self, '_user'):# 错误处理with wrap_attributeerrors():self._authenticate()return self._user
进入认证
self._authenticate()
# 需要注意的是def user(self)的这个self, 其实是request参数def _authenticate(self):'''循环 self.authenticators其实就是 request.authenticators,相当于是def get_authenticators(self):return [auth() for auth in self.authentication_classes]'''for authenticator in self.authenticators:try:user_auth_tuple = authenticator.authenticate(self)except exceptions.APIException:self._not_authenticated()raise....
user_auth_tuple = authenticator.authenticate(self)
def authenticate(self, request):return (self.force_user, self.force_token)
2.2、入门示例
- 模型
class Users(models.Model):username = models.CharField(max_length=32)pwd = models.CharField(max_length=12)class Token(models.Model):token = models.CharField(max_length=64)user = models.OneToOneField(to=Users, to_field="id", on_delete=models.CASCADE)
- 登陆
class Login(APIView):def post(self, request, *args, **kwargs):response = {"status": 1000, "msg": "登陆成功"}username = request.data.get("uesrname")pwd = request.data.get("pwd")print(request.data)ret = Users.objects.filter(username=username, pwd=pwd).first()if not ret:token = uuid.uuid4()Token.objects.create(token=token, user=ret)response["token"] = tokenelse:response["status"] = 1001response["msg"] = "请先登陆"return JsonResponse(response, safe=False)
- 认证
class Auth:# 源码中的这一个 user_auth_tuple = authenticator.authenticate(self)# self就是需要传递的参数def authenticate(self, request):token = request.query_params.get("token")ret = Token.objects.filter(token=token).first()if not ret:raise exceptions.APIException("请先登陆")return ret.user, ret
- 认证的模型
# 在需要被定义认证的类下中写, 需要注意的是,这里最多只能写三个,
# 并且如果AUth有返回值,后面的认证组件就不会在执行
class Mybookdetail(APIView):# 在需要认证的模型上添加authentication_classes = [Auth, ]
2.3、使用
2.3.1、全局使用
# # settings.py文件中定义, 所有的组件都可以放在这里
REST_FRAMEWORK = {"DEFAULT_AUTHENTICATION_CLASSES": ["app01.rest_auth.Auth"]
}
# 需要注意的是,如果定义了全局,那么直接使用login也会受到限制
2.3.2、局部使用\禁用
# 局部禁用
class Mybookdetail(APIView):authentication_classes = [] # 直接设置为空就行# 局部使用
class Mybookdetail(APIView):authentication_classes = [PostAuth, ]
2.3.4、BaseAuthentication
# 继承基础组件, 也可以不继承
from rest_framework.authentication import BaseAuthentication
# 这个基础组件其实啥也没写, 关键在于就是继承authenticate_header头部类class BaseAuthentication(object):def authenticate(self, request):raise NotImplementedError(".authenticate() must be overridden.")def authenticate_header(self, request):pass
2.4、忽略GET
# 1、先配置全局使用
# 2、允许GET属性查看, 其它的方法都需要登陆才能操作
class PostAuth(BaseAuthentication):def authenticate(self, request):http_method_names = ['post', 'put', 'patch', 'delete', 'head', 'options', 'trace']print(request.method)if request.method.lower() in http_method_names:token = request.query_params.get("token")ret = Token.objects.filter(token=token).first()if not ret:raise exceptions.APIException("请先登陆")return ret.user, retreturn
3、demo
公共使用
- setting.py
# 让全局生效
REST_FRAMEWORK = {"DEFAULT_AUTHENTICATION_CLASSES": ["app01.appAuthenticate.App01_authent", ]
}
- urls.py
from django.contrib import admin
from django.urls import path
from app01 import viewsurlpatterns = [path('admin/', admin.site.urls),path("mybook/", views.Mybook.as_view(), name="mybook"),path("login/", views.Login.as_view(), name="login"),path("logout/", views.logout, name="logout"),
]
logout
def logout(request):auth.logout(request)return JsonResponse({"status": 1000, "msg": "退出成功"})class Mybook(APIView):def get(self, request, *args, **kwargs):response = {"status": 1000, "msg": None}book_list = Book.objects.all()if all([book_list, ]):ser = BookSerializer(book_list, many=True)response["data"] = ser.dataresponse["msg"] = "查询成功"else:response["msg"] = "查询列表为空"return JsonResponse(response)
3.1、token判断
- 模型
from django.db import models
from django.contrib.auth.models import Userclass UserToken(models.Model):token = models.CharField(max_length=64)user = models.OneToOneField(to=User, to_field="id", on_delete=models.CASCADE)
- view
from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from app01.appSerializer import BookSerializer
from app01.models import *
from django.http import JsonResponse
from django.contrib import auth
import uuidclass Login(APIView):authentication_classes = []def get(self, request):return render(request, "test.html")def post(self, request):response = {"status": 1000, "msg": "登陆成功"}username = request.data.get("username")pwd = request.data.get("pwd")ret = auth.authenticate(request, username=username, password=pwd)if ret:auth.login(request, ret)token = uuid.uuid4()# 存到session中进行判断 request.session["token"] = str(token)UserToken.objects.update_or_create(user=ret, defaults={"token": token})else:response["msg"] = "登陆失败"return JsonResponse(response)
- 认证
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from app01.models import *# Create your views here.class App01_authent(BaseAuthentication):def authenticate(self, request):try:token = request.session["token"]if token:ret = UserToken.objects.filter(token=token).first()if not ret:raise exceptions.APIException("认证失败")return ret.user, tokenexcept Exception:raise exceptions.APIException("请先登陆")
3.2、session表中判断
在自定义token减少操作
App01_authent
class App01_authent(BaseAuthentication):def authenticate(self, request):try:# 取出用户的 session, 如果没有登陆数据库中不会保存token = request.session.session_keyif token:ret = Session.objects.filter(session_key=token).first()if not ret:raise exceptions.APIException("认证失败")# 返回用户,跟token, return auth.get_user(request), tokenexcept Exception:raise exceptions.APIException("请先登陆")
views
class Login(APIView):authentication_classes = []def get(self, request):return render(request, "test.html")def post(self, request):response = {"status": 1000, "msg": "登陆成功"}username = request.data.get("username")pwd = request.data.get("pwd")ret = auth.authenticate(request, username=username, password=pwd)if ret:auth.login(request, ret)else:response["msg"] = "登陆失败"return JsonResponse(response)
python-restful-02-组件(序列化\认证)相关推荐
- 两个月不到,我是如何从Python新手成长为谷歌认证TensorFlow开发者的?
点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 来自:机器之心 因为新冠疫情宅家无事可做,印度尼西亚一位应用数学学生 Grady Ma ...
- python建立数据库并序列化_python之数据的序列化
参考博客:http://www.cnblogs.com/yyds/p/6563608.html 数据的序列化功能表 json.dumps() 将python数据类型转换为(json)字符串 json. ...
- python建立数据库并序列化_Python之数据序列化(json、pickle、shelve)
一.python类型数据和JSON数据格式互相转换 pthon 中str类型到JSON中转为unicode类型,None转为null,dict对应object 二. 序列化/反序列化 将对象转换为可通 ...
- python中常用的序列化模块_使用pickle模块对python对象进行序列化
pickle模块是Python自带的一个标准模块,专用于Python各种对象的序列化和反序列化,可用于Python内置的各种数据对象(Python中一切都是对象),也可用于程序员自定义的类和对象. p ...
- 一文学会Python标准库struct序列化与反序列化
使用Python标准库struct序列化Python整数.实数.字节串时,需要使用struct模块的pack()函数把对象按指定的格式进行序列化,然后使用文件对象的write()方法将序列化的结果字节 ...
- Python 实现简单的客户端认证
更多编程教程请到:菜鸟教程 https://www.piaodoo.com/ 友情链接: 高州阳光论坛https://www.hnthzk.com/ 人人影视http://www.op-kg.com/ ...
- “结巴”中文分词:做最好的 Python 中文分词组件
jieba "结巴"中文分词:做最好的 Python 中文分词组件 "Jieba" (Chinese for "to stutter") C ...
- EN 12259-3喷水灭火系统干式报警阀组件—CE认证
喷水灭火系统干式报警阀组件CE认证(欧盟强制认证)-简介 在欧盟市场"CE"标志属强制性认证标志,以表明产品符合欧盟<技术协调与标准化新方法>指令的基本要求.这是欧盟法 ...
- 3、Python 中文分词组件Jieba
在自然语言处理中,分词是一项最基本的技术.中文分词与英文分词有很大的不同,对英文而言,一个单词就是一个词,而汉语以字为基本书写单位,词语之间没有明显的区分标记,需要人为切分.现在开源的中文分词工具有 ...
- Python 学习 02 —— Python如何爬取数据
文章目录 系列文章 二.Python 爬 虫 1.任务介绍 2.简介 3.基本流程 3.1.准备工作 3.1.1.分析页面 3.1.2.编码规范 3.1.3.导入模块 3.1.4.程序流程 3.2.获 ...
最新文章
- postgresql(pg)数据库简介
- 注解由谁读取并解析的?
- windows下vagrant的安装使用
- 104 规约模拟器linux,变电站自动化系统调试装置 Substation automation system debugging device...
- 苹果爸爸发飙,封杀 React Native?
- 【开源资讯】开源文档管理系统 Wizard 1.2.5 发布
- SeSe 2005-02-11 -- 2005-02-12
- 记录一下:调试了虹软的人脸识别sdk,存到数据库中
- 处理minidump文件用到的“工具”的分享
- linux 修改密码 authen,Linux系统下root用户执行passwd修改密码时报错Authentication to
- GO的lua虚拟机 gopher-lua
- 前端容易忽略的 debugger 调试技巧
- 2022-03微软漏洞通告
- 如何彻底禁用谷歌Chrome更新
- vue项目微信公众号title设置和调用接口动态修改
- 设某种二叉树有如下特点:每个结点要么是叶子结点,要么有2棵子树。假如一棵这样的二叉树中有m(m0)个叶子结点,那么该二叉树上的结点总数为( )。
- matlab生成棋盘格网的命令,Matlab 画棋盘格
- HBase-Region的拆分与合并
- android的wifi网卡移植详细过程已经通用驱动的问题
- “达内”JAVA技术培训有感(二)