add restful support

This commit is contained in:
yumoqing 2019-07-29 10:01:11 +08:00
parent 3290fe1f97
commit 260c38d637
6 changed files with 160 additions and 23 deletions

14
ahserver/error.py Normal file
View File

@ -0,0 +1,14 @@
def Error(errno='undefined error',msg='Error'):
return {
"status":"Error",
"data":{
"message":msg,
"errno":errno
}
}
def Success(data):
return {
"status":"OK",
"data":data
}

View File

@ -20,10 +20,6 @@ from appPublic.uniqueID import setNode,getID
from appPublic.unicoding import unicoding,uDict,uObject from appPublic.unicoding import unicoding,uDict,uObject
from appPublic.Singleton import SingletonDecorator from appPublic.Singleton import SingletonDecorator
from sql.crud import _CRUD,CRUD
# from sql.sqlorAPI import DBPools,runSQL,runSQLPaging,runSQLIterator
# from sql.sqlorAPI import getTables,getTableFields,getTablePrimaryKey
# from sql.sqlorAPI import getTableForignKeys,runSQLResultFields
from sqlor.dbpools import DBPools from sqlor.dbpools import DBPools
@ -167,7 +163,6 @@ def initEnv():
g.folderInfo = folderInfo g.folderInfo = folderInfo
g.abspath = abspath g.abspath = abspath
g.request2ns = request2ns g.request2ns = request2ns
g.CRUD = CRUD
g.data2xlsx = data2xlsx g.data2xlsx = data2xlsx
g.xlsxdata = XLSXData g.xlsxdata = XLSXData
g.openfile = openfile g.openfile = openfile

View File

@ -19,7 +19,7 @@ from aiohttp.web_routedef import AbstractRouteDef
from appPublic.jsonConfig import getConfig from appPublic.jsonConfig import getConfig
from appPublic.MiniI18N import getI18N from appPublic.MiniI18N import getI18N
from appPublic.dictObject import DictObject from appPublic.dictObject import DictObject, multiDict2Dict
from .baseProcessor import getProcessor from .baseProcessor import getProcessor
from .xlsxdsProcessor import XLSXDataSourceProcessor from .xlsxdsProcessor import XLSXDataSourceProcessor
@ -27,19 +27,7 @@ from .sqldsProcessor import SQLDataSourceProcessor
from .serverenv import ServerEnv from .serverenv import ServerEnv
from .url2file import Url2File from .url2file import Url2File
from .filestorage import FileStorage from .filestorage import FileStorage
from .restful import DBCrud
def multiDict2Dict(md):
ns = {}
for k,v in md.items():
ov = ns.get(k,None)
if ov is None:
ns[k] = v
elif type(ov) == type([]):
ov.append(v)
ns[k] = ov
else:
ns[k] = [ov,v]
return ns
def getHeaderLang(request): def getHeaderLang(request):
al = request.headers.get('Accept-Language') al = request.headers.get('Accept-Language')
@ -70,6 +58,10 @@ class ProcessorResource(StaticResource):
append_version=append_version) append_version=append_version)
gr = self._routes.get('GET') gr = self._routes.get('GET')
self._routes.update({'POST':gr}) self._routes.update({'POST':gr})
self._routes.update({'PUT':gr})
self._routes.update({'OPTIONS':gr})
self._routes.update({'DELETE':gr})
self._routes.update({'TRACE':gr})
self.y_processors = [] self.y_processors = []
self.y_prefix = prefix self.y_prefix = prefix
self.y_directory = directory self.y_directory = directory
@ -90,7 +82,7 @@ class ProcessorResource(StaticResource):
real_path = os.path.abspath(rp) real_path = os.path.abspath(rp)
return real_path return real_path
async def getPostData(self,request): async def getPostData(self,request: Request) -> dict:
reader = await request.multipart() reader = await request.multipart()
if reader is None: if reader is None:
md = await request.post() md = await request.post()
@ -161,8 +153,6 @@ class ProcessorResource(StaticResource):
return await self.getPostData(request) return await self.getPostData(request)
ns = multiDict2Dict(request.query) ns = multiDict2Dict(request.query)
return ns return ns
print('** ret=',ret,request.query)
return ns
self.y_env.i18n = serveri18n self.y_env.i18n = serveri18n
self.y_env.i18nDict = i18nDICT self.y_env.i18nDict = i18nDICT
@ -172,6 +162,19 @@ class ProcessorResource(StaticResource):
self.y_env.request2ns = getArgs self.y_env.request2ns = getArgs
self.y_env.resource = self self.y_env.resource = self
path = request.path path = request.path
config = getConfig()
if config.website.dbrest and path.startswith(config.website.dbrest):
pp = path.split('/')[2:]
if len(pp)<2:
raise HTTPNotFound
dbname = pp[0]
tablename = pp[1]
id = None
if len(pp) > 2:
id = pp[2]
crud = DBCrud(request,dbname,tablename,id=id)
return await crud.dispatch()
for word, handlername in self.y_processors: for word, handlername in self.y_processors:
if path.endswith(word): if path.endswith(word):
Klass = getProcessor(handlername) Klass = getProcessor(handlername)

123
ahserver/restful.py Normal file
View File

@ -0,0 +1,123 @@
import os
import re
from aiohttp.web_urldispatcher import StaticResource, _WebHandler, PathLike
from aiohttp.web_urldispatcher import Optional, _ExpectHandler
from aiohttp.web_urldispatcher import Path
from aiohttp.web_response import Response, StreamResponse
from aiohttp.web_exceptions import (
HTTPException,
HTTPExpectationFailed,
HTTPForbidden,
HTTPMethodNotAllowed,
HTTPNotFound,
)
from aiohttp import web
from aiohttp.web_fileresponse import FileResponse
from aiohttp.web_request import Request
from aiohttp.web_response import Response, StreamResponse
from aiohttp.web_routedef import AbstractRouteDef
from aiohttp.web import json_response
from sqlor.crud import CRUD
from appPublic.dictObject import multiDict2Dict
from appPublic.jsonConfig import getConfig
from .error import Error,Success
DEFAULT_METHODS = ('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE')
class RestEndpoint:
def __init__(self):
self.methods = {}
for method_name in DEFAULT_METHODS:
method = getattr(self, method_name.lower(), None)
if method:
self.register_method(method_name, method)
def register_method(self, method_name, method):
self.methods[method_name.upper()] = method
async def dispatch(self):
method = self.methods.get(self.request.method.upper())
if not method:
raise HTTPMethodNotAllowed('', DEFAULT_METHODS)
return await method()
class DBCrud(RestEndpoint):
def __init__(self, request,dbname,tablename, id=None):
print(f'***{dbname}*{tablename}*{id}************')
super().__init__()
self.dbname = dbname
self.tablename = tablename
self.request = request
self.id = id
try:
self.crud = CRUD(dbname,tablename)
except Exception as e:
print('e=',e)
raise HTTPNotFound
async def options(self) -> Response:
try:
d = await self.crud.I()
return json_response(Success(d))
except Exception as e:
print(e)
return json_response(Error(errno='metaerror',msg='get metadata error'))
async def get(self) -> Response:
"""
query data
"""
try:
ns = multiDict2Dict(self.request.query)
if self.id is not None:
ns['__id'] = self.id
d = await self.crud.R(NS=ns)
return json_response(Success(d))
except Exception as e:
print(e)
return json_response(Error(errno='search error',msg='search error'))
async def post(self):
"""
insert data
"""
try:
ns = multiDict2Dict(await self.request.post())
d = await self.crud.C(ns)
return json_response(Success(d))
except Exception as e:
print(e)
return json_response(Error(errno='add error',msg='add error'))
async def put(self):
"""
update data
"""
try:
ns = multiDict2Dict(await self.request.post())
d = await self.crud.U(ns)
return json_response(Success(''))
except Exception as e:
print(e)
return json_response(Error(errno='update error',msg='update error'))
async def delete(self, request: Request, instance_id):
"""
delete data
"""
try:
ns = multiDict2Dict(self.request.query)
d = await self.crud.D(ns)
return json_response(Success(d))
except Exception as e:
print(e)
return json_response(Error(erron='delete error',msg='error'))

View File

@ -43,6 +43,7 @@
"index.dspy", "index.dspy",
"index.md" "index.md"
], ],
"dbrest":"/dbs",
"visualcoding":{ "visualcoding":{
"default_root":"/samples/vc/test", "default_root":"/samples/vc/test",
"userroot":{ "userroot":{

View File

@ -11,4 +11,5 @@ sqlor
jinja2 jinja2
ujson ujson
openpyxl openpyxl
#appPublic appPublic
patterncoding