web.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. # -*- coding: utf-8 -*-
  2. """
  3. demeter
  4. name:web.py
  5. author:rabin
  6. """
  7. #from gevent import monkey
  8. #monkey.patch_all()
  9. #import gevent
  10. import functools
  11. import os
  12. import json
  13. import threading
  14. from demeter.core import *
  15. import tornado.web
  16. import tornado.ioloop
  17. import tornado.httpserver
  18. import tornado.httpclient
  19. import tornado.concurrent
  20. class Base(tornado.web.RequestHandler):
  21. def set_default_headers(self):
  22. self.set_header("Access-Control-Allow-Origin", "*")
  23. self.set_header("Access-Control-Allow-Headers", "x-requested-with")
  24. self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
  25. def initialize(self):
  26. try:
  27. Demeter.request = self
  28. self.assign()
  29. self.page()
  30. self.cookie()
  31. self.setting()
  32. except Exception as e:
  33. return
  34. def get_current_user(self):
  35. return self.get_secure_cookie(self.KEYS[0])
  36. def assign(self):
  37. self.data = {}
  38. self.data['setting'] = Demeter.config['setting']
  39. self.data['base'] = Demeter.config['base']
  40. def cookie(self):
  41. for key in self.KEYS:
  42. cookie = None
  43. """
  44. if key in self.data['base']:
  45. cookie = self.data['base'][key]
  46. """
  47. if not cookie:
  48. cookie = self.get_secure_cookie(key)
  49. #cookie = self.get_cookie(key)
  50. if not cookie:
  51. value = self.input(key)
  52. if value:
  53. #self.set_secure_cookie(key, value)
  54. self.data['setting'][key] = value
  55. else:
  56. self.data['setting'][key] = 0
  57. else:
  58. self.data['setting'][key] = cookie
  59. def page(self):
  60. Demeter.config['page'] = {}
  61. page = self.input('page')
  62. if page:
  63. Demeter.config['page']['ajax'] = True
  64. else:
  65. Demeter.config['page']['ajax'] = False
  66. page = 1
  67. Demeter.config['page']['current'] = page
  68. Demeter.config['page']['total'] = 0
  69. self.data['page'] = Demeter.config['page']
  70. def search(self):
  71. data = self.request.arguments
  72. self.data['search'] = {}
  73. self.data['update'] = {}
  74. for key in data:
  75. if 'search_' in key:
  76. index = key.replace('search_', '')
  77. i = 0
  78. for a in data[key]:
  79. data[key][i] = a.decode()
  80. self.data['search'][index] = ",".join(data[key])
  81. if 'update_' in key:
  82. index = key.replace('update_', '')
  83. i = 0
  84. for a in data[key]:
  85. data[key][i] = a.decode()
  86. i = i + 1
  87. self.data['update'][index] = ",".join(data[key])
  88. def input(self, key, value=None):
  89. return self.get_argument(key, value)
  90. def inputs(self, key):
  91. return self.get_arguments(key)
  92. def service(self, name):
  93. return Demeter.service(name)
  94. def model(self, name):
  95. return Demeter.model(name)
  96. def set(self, **kwd):
  97. self.data['common'] = kwd
  98. self.data['common']['argvs'] = ''
  99. def show(self, name):
  100. self.view('common/'+name+'.html')
  101. def list(self, model, order = 'cdate desc'):
  102. self.data['state'] = self.input('state', True)
  103. self.data['list'] = self.service('common').list(model, state=self.data['state'], search=self.data['search'], page=True, order=order)
  104. def one(self, model, **kwd):
  105. self.data['info'] = {}
  106. if 'id' not in kwd and self.input('id'):
  107. id = self.input('id')
  108. if id:
  109. kwd['id'] = id
  110. if kwd:
  111. self.data['info'] = self.service('common').one(model, **kwd)
  112. def update(self, model, msg='', id=0, **kwd):
  113. if not self.data['auth']:
  114. self.auth()
  115. else:
  116. if id <= 0:
  117. id = self.input('id')
  118. if kwd:
  119. info = self.service('common').one(model, **kwd)
  120. if info and (id != info['id']):
  121. self.out(msg)
  122. return
  123. state = self.service('common').update(model, id, self.data['update'])
  124. self.log(model, 'update', self.data['update'])
  125. self.out('yes', {'id':state})
  126. return state
  127. def drop(self, model):
  128. if not self.data['auth']:
  129. self.auth()
  130. else:
  131. id = self.input('id')
  132. state = self.input('state', False)
  133. state = self.service('common').delete(model, id, state)
  134. self.log(model, 'delete', {id:id, state:state})
  135. self.out('yes', {'state':state})
  136. def log(self, model, method, data):
  137. if 'admin' in self.data['setting'] and self.data['setting']['admin'] > 0:
  138. insert = {}
  139. insert['admin_id'] = self.data['setting']['admin']
  140. insert['model'] = model
  141. insert['method'] = method
  142. insert['data'] = json.dumps(data)
  143. self.service('common').update('manage_log', None, insert)
  144. def view(self, name):
  145. if not self.data['auth']:
  146. self.auth()
  147. else:
  148. config = Demeter.config[Demeter.web]
  149. path = ''
  150. if 'mobile' in config:
  151. mobile = Demeter.checkMobile(self.request)
  152. if mobile:
  153. path = 'mobile/'
  154. else:
  155. path = 'pc/'
  156. self.render(path + name, data=self.data, Demeter=Demeter)
  157. def auth(self):
  158. self.out('您没有权限')
  159. def out(self, msg='', data={}, code=0):
  160. callback = self.input('callback')
  161. function = self.input('function')
  162. result = Demeter.out(msg=msg, data=data, code=code, callback=callback, function=function)
  163. self.write(result)
  164. if not data:
  165. from tornado.web import Finish
  166. raise Finish()
  167. else:
  168. self.finish()
  169. class Web(object):
  170. @classmethod
  171. def auth(self, method):
  172. return tornado.web.authenticated(method)
  173. @classmethod
  174. def setting(self, method):
  175. return self.async(method)
  176. @staticmethod
  177. def async(method):
  178. @tornado.web.asynchronous
  179. @tornado.gen.coroutine
  180. @functools.wraps(method)
  181. def callback(self, *args, **kwargs):
  182. #self._auto_finish = False
  183. try:
  184. result = method(self, *args, **kwargs)
  185. return result
  186. except Exception as e:
  187. import traceback
  188. error = traceback.format_exc()
  189. if 'Finish' in error:
  190. return
  191. else:
  192. traceback.print_exc()
  193. try:
  194. return self.view('404.html')
  195. except Exception as e:
  196. return self.out('404')
  197. #return gevent.spawn(method, self, *args, **kwargs)
  198. return callback
  199. @classmethod
  200. def init(self, application):
  201. for v in application:
  202. self.load(v)
  203. @classmethod
  204. def load(self, package):
  205. """
  206. path = os.path.split(os.path.realpath(file))[0] + '/'
  207. sys.path.append(path)
  208. files = self.file(path)
  209. """
  210. url = []
  211. for key in Demeter.getPackage(package):
  212. module = Demeter.getObject(key)
  213. url = self.url(module, key, url)
  214. Demeter.route = Demeter.route + url
  215. """
  216. @staticmethod
  217. def file(path):
  218. files = os.listdir(path)
  219. result = []
  220. for key in files:
  221. if key and '.DS_Store' not in key and '__' not in key and 'pyc' not in key:
  222. key = key.replace('.py', '')
  223. result.append(key)
  224. return result
  225. """
  226. @staticmethod
  227. def url(module, key, url):
  228. str = Demeter.getMethod(module)
  229. key = key.split('.')[-1]
  230. for i,j in str:
  231. act = ''
  232. if '_path' in i:
  233. act = i.replace('_path', '')
  234. if '_html' in i:
  235. act = i.replace('_html', '.html')
  236. if act:
  237. attr = getattr(module, i)
  238. if key == 'main' and act == 'index':
  239. url.append((r'/', attr))
  240. elif key == act or act == 'index':
  241. url.append((r'/'+key, attr))
  242. url.append((r'/'+key+'/'+act, attr))
  243. return url
  244. @classmethod
  245. def start(self, application=[]):
  246. t = threading.Thread(target=lambda: self.start_server(application))
  247. t.start()
  248. @classmethod
  249. def start_server(self, application=[]):
  250. self.init(application)
  251. if 'route' in Demeter.config['setting']:
  252. Demeter.echo(Demeter.route)
  253. config = Demeter.config[Demeter.web]
  254. cookie = False
  255. if 'tornado' not in Demeter.config:
  256. Demeter.config['tornado'] = {}
  257. if 'xsrf_cookies' in config:
  258. cookie = Demeter.bool(config['xsrf_cookies'])
  259. settings = dict({
  260. "static_path": Demeter.webPath + 'static',
  261. "template_path": Demeter.webPath + 'templates',
  262. "cookie_secret": 'demeter',
  263. "login_url": '/user/login',
  264. "xsrf_cookies": cookie,
  265. "debug": Demeter.bool(config['debug']),
  266. #"autoreload": Demeter.bool(config['autoreload']),
  267. "port": config['port'],
  268. "max_buffer_size": int(config['max_buffer_size']),
  269. "process": int(config['process'])
  270. }, **Demeter.config['tornado'])
  271. com = ('cookie_secret', 'login_url', 'static_path', 'template_path')
  272. for v in com:
  273. if v in config:
  274. settings[v] = config[v]
  275. handlers = []
  276. def application_setting():
  277. handlers.append((r"/upload/(.*)", tornado.web.StaticFileHandler, {"path": Demeter.path + 'runtime/upload/'}))
  278. handlers.append((r"/files/(.*[\.png|\.jpg|\.gif|\.js|\.css|\.font|\.fonts|\.ttc|\.ttf|\.woff|\.woff2|\.fon|\.eot|\.otf])", tornado.web.StaticFileHandler, {"path": Demeter.path + 'runtime/files/'}))
  279. handlers.append((r"/qrcode/(.*)", tornado.web.StaticFileHandler, {"path": Demeter.path + 'runtime/qrcode/'}))
  280. handlers.append((r"/camera/(.*)", tornado.web.StaticFileHandler, {"path": Demeter.path + 'runtime/camera/'}))
  281. handlers.append((r"/static/(.*)", tornado.web.StaticFileHandler, {"path": "static"}))
  282. handlers.append((r"/(apple-touch-icon\.png)", tornado.web.StaticFileHandler, dict(path=settings['static_path'])))
  283. handlers.extend(Demeter.route)
  284. application_setting()
  285. application = tornado.web.Application(handlers=handlers, **settings)
  286. if Demeter.checkPy3():
  287. import asyncio
  288. asyncio.set_event_loop(asyncio.new_event_loop())
  289. if settings['debug'] == True:
  290. application.listen(settings['port'])
  291. tornado.ioloop.IOLoop.instance().start()
  292. else:
  293. server = tornado.httpserver.HTTPServer(application, settings['max_buffer_size'])
  294. server.bind(settings['port'])
  295. server.start(settings['process'])
  296. try:
  297. Demeter.echo('running on port %s' % settings['port'])
  298. tornado.ioloop.IOLoop.instance().start()
  299. except KeyboardInterrupt:
  300. tornado.ioloop.IOLoop.instance().stop()