self 声明实例方法 ↙↙↙
class Gitee:
def __repr__(self): # self 声明实例方法
return "Gitee登录"
class Ding:
def __repr__(self):
return "Ding登录"
# 当打印实例对象的时候,打印的结果就是__repr__的返回值
@classmethod 声明类方法 ↙↙↙
class Book:
def __init__(self, title):
self.title = title
# 声明类方法
@classmethod
def create(cls, title):
book = cls(title)
return book
if __name__ == '__main__':
book1 = Book('python')
print(book1.title) # python
book2 = Book.create('python2')
print(book2.title) # python2
@staticmethod 声明静态方法 ↙↙↙
# 简单工厂
class SimpleFactory:
# 产品
@staticmethod
def product(name):
if name == "Gitee":
return Gitee()
else:
return Ding()
if __name__ == '__main__':
product = SimpleFactory.product("Gitee")
print(product) # Gitee登录
print(Gitee()) # Gitee登录
声明抽象方法 @abstractmethod
目的:父类声明 自定义func()方法 继承类必须使用,重写func()方法,不使用则报错 ↙↙↙
# 抽象工厂模式
from abc import ABCMeta, abstractmethod
# 声明元类
class TestMeta(metaclass=ABCMeta):
def __init__(self):
self.a = 1
@abstractmethod
def func(self):
pass
第一种:super() 调父类
第二种:TestMeta 调父类 ↙↙↙
class TestOne(TestMeta):
def __init__(self):
super().__init__()
# TestMeta.__init__()
self.b = 2
# 声明父类.__init__()之后 不会覆盖父类init原有属性
# TestMeta重写抽象方法(@abstractmethod声明的抽象方法必须重写,不然报错)
def func(self):
print('马可波罗')
a = TestOne()
print(a.a) # 输出父类TestMeta a属性的值 1
print(a.b) # 输出TestOne b属性的值 2
在类中,调用异步方法 ↙↙
import asyncio
class A:
async def get(self, id):
data = {
'git_id': 1, # int类型
'git_name': id,
'git_username': '3'
}
return data
async def bb(self):
f = await self.get(5)
print(type(f)) # dict
print(f['git_name']) # int 5
# # 注:直接使用下面方法报错 ↙↙↙
# f = await self.get(5)['git_name']
# print(f)
return 'grhtn'
if __name__ == '__main__':
a = A()
asyncio.run(a.bb())
异步GIT三方登录 抽象工厂模式 ↙↙↙
根目录创建scripts文件 -> tests_factory.py
导包
import json
import random
import string
import httpx # 异步网络请求
# 三方登录需要的个人配置
from APP_ID import gitee_redirect_url, gitee_client_secret, gitee_client_id
# 异步链接 和 平台类型
from config import db, Site_type
from model.model import User
# jwt的封装
from utils.m_jwt import MyJwt
from utils.md5 import md5_jm
# 抽象类,抽象方法
from abc import ABCMeta, abstractmethod
使用 @abstractmethod方法 做一个抽象工厂 ↙↙↙
(抽象类 父类)↙↙↙
class LoginProvider(metaclass=ABCMeta):
# 跳转拼接url
@abstractmethod
def get_url(self, code):
pass
# 获取access_token
@abstractmethod
async def get_token(self, url, code):
pass
# 获取用户信息
@abstractmethod
async def get_info(self, access_token):
pass
# 用户信息存储
@abstractmethod
async def set_user(self, access_token, git_info):
pass
(子类) Git三方登录封装方法↙↙↙
class GiteeProvider(LoginProvider):
# 换code的地址
def get_url(self, code):
url = f"https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={gitee_client_id}\
&redirect_uri={gitee_redirect_url}&client_secret={gitee_client_secret}"
return url
# 三方登录的token
async def get_token(self, url, code):
async with httpx.AsyncClient() as client:
res = await client.post(
url, timeout=20
)
# timeout 默认请求等待5秒
data = json.loads(res.text)
access_token = data['access_token']
# refresh_token = data['refresh_token']
return access_token
# 获取用户信息
async def get_info(self, access_token):
async with httpx.AsyncClient() as client:
res2 = await client.get(f"https://gitee.com/api/v5/user?access_token={access_token}", timeout=20)
user_info = json.loads(res2.text)
if not user_info:
return '信息错误'
# gitee三方登录 id唯一 但用户名不唯一(采用id+用户名的方式存储数据库用户名)
git_info = {
'git_id': user_info['id'], # int类型
'git_name': user_info['name'],
'git_username': str(user_info['id']) + user_info['name']
}
return git_info
# 用户信息存储
async def set_user(self, access_token, git_info):
# 通过gitee的id判断该用户gitee账号是否已经注册
mj = MyJwt()
try:
user_info = await db.get(
User.select().where((User.username == git_info['git_username']) & (
User.site_type == Site_type['Gitee']['num'])))
except Exception as e:
print(e)
code4 = ''.join(random.sample(string.ascii_letters + string.digits, 4))
pwd_new = md5_jm(code4)
await db.create(User, username=git_info['git_username'], password=pwd_new,
site_type=Site_type['Gitee']['num'])
user_info = await db.get(
User.select().where(
(User.username == git_info['git_username']) & (User.site_type == Site_type['Gitee']['num'])))
token = mj.encode_date({'username': user_info.username, 'site_type': Site_type['Gitee']['num']})
return 'http://127.0.0.1:8080/?username=' + git_info['git_username'] + '&token=' + token
根目录下的Views文件
(父类)视图 base.py ↙↙↙
# 基础视图
import json
import tornado.web
# 视图
class BaseHandler(tornado.web.RequestHandler):
# 通过继承父类tornado.web.RequestHandler 进行重写
# 初始化方法(如果与父类方法重名,必须定义__init__方法,防止覆盖父类(finish与父类方法重名))
def __init__(self, *args, **kwargs):
tornado.web.RequestHandler.__init__(self, *args, **kwargs)
# 跨域
def set_default_headers(self):
# 请求来源
self.set_header('Access-Control-Allow-Origin', '*')
# 请求方式
self.set_header('Access-Control-Allow-Methods', 'POST,GET,PUT,DELETE,TRACE,HEAD,PATCH,OPTIONS')
# 请求头
self.set_header('Access-Control-Allow-Headers', '*')
def options(self):
self.set_status(204)
self.finish()
def finish(self, chunk=None):
if chunk is not None and not isinstance(chunk, bytes):
chunk = json.dumps(chunk, indent=4, sort_keys=True, default=str, ensure_ascii=False)
try:
tornado.web.RequestHandler.write(self, chunk)
except Exception as e:
pass
tornado.web.RequestHandler.finish(self)
(子类)视图 user.py -> Gitee回调 ↙↙↙
class GiteeBack(BaseHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.gitee = GiteeProvider()
async def get(self):
code = self.get_argument('code')
url = self.gitee.get_url(code)
access_token = await self.gitee.get_token(url, code)
git_info = await self.gitee.get_info(access_token)
redirect_url = await self.gitee.set_user(access_token, git_info)
return self.redirect(redirect_url)