【Python】【Flask】【一】demo

 

【database_operator.py】


import os, re
from importlib.machinery import SourceFileLoader
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.declarative.api import DeclarativeMeta
from .exceptions import DataBaseOperationException
from .utility import Utility

os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.AL32UTF8'

def error_handle(func):
def wrapper(database_operator, *args, **kwargs):
try:
return func(database_operator, *args, **kwargs)
except SQLAlchemyError as e:
database_operator.session_provider.rollback()
raise e
finally:
database_operator.session_provider.close()
return wrapper


class DataOperatorSingleton(type):
def __init__(cls, name, bases, dict):
super(DataOperatorSingleton, cls).__init__(name, bases, dict)
cls.__instance = None

def __call__(cls, *args, **kwargs):
_key = str(args) + str(kwargs)
if cls.__instance is None:
cls.__instance = {
_key: super(DataOperatorSingleton, cls).__call__(*args, **kwargs)
}

elif _key not in cls.__instance:
cls.__instance.update({
_key: super(DataOperatorSingleton, cls).__call__(*args, **kwargs)
})

return cls.__instance.get(_key)

class DataBaseOperator(object, metaclass=DataOperatorSingleton):
def __init__(self, model_path_str, env='qa', split_tb_hook=None, split_db_hook=None):
self.__env = env
self.__table_cls = None
self.session_provider = None
self.__db_hook = None
self.__tb_hook = None
self.__is_select = False
self.utl = Utility()

db_model = re.search(r'(\w+)\.py$', model_path_str).group(1)
try:
load_path = self.utl.intersection_of_path(model_path_str)
self.__module = SourceFileLoader(db_model, load_path).load_module()
except ModuleNotFoundError:
raise ModuleNotFoundError('The "{0}" mapping classes has not yet been generated!').format(db_model)

self.__connect_info = self.__module.CONNECT_INFO
self.__database_type = self.__module.CONNECT_INFO['connect_tag']
if not self.__db_hook:
self._build_session_provider()

def __get_table_cls(self, filter_d):
for cls_name in self.__module.__dict__.keys():
if re.match(r'^(t_)?{0}(_view)?$'.format(self.__org_table_name), self.utl.camel_to_underline(cls_name)):
self.__table_cls = getattr(self.__module, cls_name)
break
else:
continue

if self.__table_cls is None:
raise DataBaseOperationException('The {} table class is not definition!'.format(self.__org_table_name))

def _build_session_provider(self):
if self.__database_type == 'mysql':
connect_string = 'mysql+pymysql://{usr}:{pwd}@{url}/{db}?charset=utf8'.format(**self.__connect_info[self.__env])
parameters = {"echo": False}
engine = create_engine(connect_string, **parameters)
session = sessionmaker(bind=engine)
self.session_provider = session()

@error_handle
def __get_table_row(self, order_by_column_name=None, result_mode='all', limit=10, **filters):
self.__is_select = True
self.__get_table_cls(filters)

self.session_provider.commit() #强制刷新缓存
sql_query = self.session_provider.query(self.__table_cls).filter_by(**filters)
if order_by_column_name:
order_by_mode, order_by_column = order_by_column_name.split('_', 1)
order_by_func = getattr(sqlalchemy, order_by_mode)
sql_query = sql_query.order_by(order_by_func(order_by_column))
return getattr(sql_query.limit(limit), result_mode)() if result_mode == 'all' else getattr(sql_query, result_mode)()

@error_handle
def __update_table_row(self, update_dict, **filters):
if not isinstance(update_dict, dict):
raise Exception('Update statement %s is wrong. ' % update_dict)

self.__is_select = False
self.__get_table_cls(filters)

self.session_provider.query(self.__table_cls).filter_by(**filters).update(update_dict)
self.session_provider.commit()

@error_handle
def __delete_table_row(self, **filters):
self.__is_select = False
self.__get_table_cls(filters)

if isinstance(self.__table_cls, sqlalchemy.Table):
sql_s = ''
_keys = list(filters.keys())

for i in range(len(_keys)):
if _keys[i] == _keys[-1]:
sql_s += '{}={}'.format(_keys[i], filters[_keys[i]])
else:
sql_s += '{}={} and '.format(_keys[i], filters[_keys[i]])

del_st = self.__table_cls.delete().where(sql_s)
self.session_provider.execute(del_st)
self.session_provider.commit()

else:
rows = self.session_provider.query(self.__table_cls).filter_by(**filters).all()
if rows is None:
raise SQLAlchemyError('Cannot be found in %s table conditions for %s' % (self.__table_cls.__tablename__, filters))
else:
for row in rows:
self.session_provider.delete(row)
self.session_provider.commit()


@error_handle
def __add_table_row(self, **insert_dict):
self.__is_select = False
self.__get_table_cls(insert_dict)

if not isinstance(insert_dict, dict):
raise Exception('Add statement %s is wrong.' % insert_dict)

if isinstance(self.__table_cls, sqlalchemy.Table):
ins = self.__table_cls.insert().values(**insert_dict)
self.session_provider.execute(ins)
else:
self.session_provider.add(self.__table_cls(**insert_dict))
self.session_provider.commit()

def __getattr__(self, item):
ghost_func = re.search(r'(^get_|^update_|^add_|^delete_)(\w+$)', item)
if ghost_func:
self.__org_table_name = ghost_func.group(2)

if 'get' in item:
return self.__get_table_row
elif 'update' in item:
return self.__update_table_row
elif 'add' in item:
return self.__add_table_row
elif 'delete' in item:
return self.__delete_table_row

else:
raise AttributeError(" '%s' object has no attribute '%s'" % (self.__class__.__name__, item))


【exceptions.py】


class DataPatternWarning(Warning):
pass

class VerifyWarning(Warning):
pass


class DataBaseOperationException(Exception):
pass

【utility.py】


import time, collections, inspect, os, imaplib, sys, hashlib, re
from faker import Factory
from functools import wraps

class Singleton(type):
def __init__(cls, name, bases, dict):
super(Singleton, cls).__init__(name, bases, dict)
cls.__instance = None

def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls.__instance

class Utility(object, metaclass=Singleton):
def __init__(self):
self.fake_cn = Factory.create('zh_CN')
self.fake_en = Factory.create()

@staticmethod
def camel_to_underline(camel_format):
'''
驼峰格式转下划线格式
:param camel_format:
:return:
'''
underline_format = ''
if isinstance(camel_format, str):
for i in range(len(camel_format)):
underline_format += (camel_format[i].isupper() and i !=0) and '_' + camel_format[i].lower() or camel_format[i].lower()
return underline_format

@staticmethod
def intersection_of_path(file_path):
'''
拼接绝对路径的文件路径,方便文件的读取
:param file_path:
:return:
'''
relative_list = os.path.normpath(file_path).split(os.sep)
sys_path_now_list = os.path.dirname(__file__).split(os.sep)[1:]
for i in range(1, len(sys_path_now_list)):
list_path = ''.join(['/%s' % y for y in sys_path_now_list[:-i]])
sys_path_dirs = os.listdir(list_path)
if relative_list[0] in sys_path_dirs:
return os.path.join(list_path, file_path)




if __name__ == '__main__':
print ( '\n\.')




[account.py]
from sqlalchemy import String, Column, DECIMAL, Date, DateTime, TIMESTAMP, Table, Text, text
from sqlalchemy.dialects.mysql import BIGINT, INTEGER, SMALLINT, VARCHAR, DATETIME
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
metedata = Base.metadata

CONNECT_INFO = {'connect_tag': 'mysql',
'qa': {'usr': 'root', 'pwd': '123', 'url': 'localhost:3306', 'db': 'account'}}


class FlaskerTbOne(Base):
__tablename__ = 'flasker_tb_one'

id = Column(INTEGER(4), primary_key=True)
title = Column(String(255), nullable=False)
text = Column(String(255), nullable=False)


[style.css]
body               { font-family: sans-serif;  backgroud: #eee; }
a, h1, h2 { color: #377BA8; }
h1, h2 { font-family: 'Georgia', serif; margin:0; }
h1 { border-bottom: 2px solid #eee; }
h2 { font-size: 1.2em; }
.page { margin: 2em auto; width: 35em; border: 5px solid #ccc;
padding: 0.8em; background: white; }
.entries { list-style: none; margin: 0; padding: 0; }
.entries li { margin: 0.8em 1.2em; }
.entries li h2 { margin-left: -1em; }
.add-entry { font-size: 0.9em; border-bottom: 1px solid #ccc; }
.add-entry dl { font-weight: bold; }
.metanav { text-align: right; font-size: 0.8em; padding: 0.3em;
margin-bottom: 1em; background: #fafafa; }
.flash { background: #CEE5F5; padding: 0.5em;
border: 1px solid #AACBE2; }
.error { background: #F0D6D6; padding: 0.5em; }



【layout.html】
<!DOCTYPE html>


<title>Flaskr</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">



<div class="page">
<h1>Flaskr</h1>
<div class="metanav">
{% if not session.logged_in %}
<a href="{{ url_for('login') }}">log in </a>
{% else %}
<a href="{{ url_for('logout') }}">log out</a>
{% endif %}

</div>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}

</div>



[login.html]
{% extends 'layout.html' %}
{% block body %}
<h2>Login</h2>
{% if error %}<p class="error"><strong>Error:</strong>{{ error }}{% endif %}
<form action="{{ url_for('login') }}" method="post">
<dl>
<dt>Username:
<dd><input type="text" name="username">
<dt>Password:
<dd><input type="password" name="password">
<dd><input type="submit" value="Login">
</dl>

</form>
{% endblock %}


[show_entities.html]
{% extends 'layout.html' %}
{% block body %}
{% if session.logged_in %}
<form action="{{ url_for('add_entry') }}" method="post" class="add-entry">
<dl>
<dt>Title:
<dd><input type="text" size="30" name="title">
<dt>Text:
<dd><textarea name="text" rows="5" cols="40"></textarea>
<dd><input type="submit" value="Share">
</dl>

</form>
{% endif %}
<ul class="entries">
{% for entry in entries %}
<li><h2>{{ entry.title }}}</h2>{{ entry.text|safe }}
{% else %}
<li><em>Unbelievable. No entries here so far </em>
{% endfor %}

</ul>
{% endblock %}



[conftest.py]



import pytest
from flasker.kernel.database_operator import DataBaseOperator

DB_MODELS_PATH = 'untitled3/flasker/models/{}.py'



def pytest_addoption(parser):
parser.addoption('--test_env', action='store', default='qa', dest='test_env', help='my option: qa or dev')

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()

setattr(item, 'rep_' + rep.when, rep)

@pytest.fixture(scope='session')
def environment(request):
return request.config.getoption('test_env')

@pytest.fixture(scope='session')
def account_data(environment):
return DataBaseOperator(DB_MODELS_PATH.format('account'), environment)



[flasker_one_test.py]
import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
import pytest



class TestFlasker(object):

@pytest.mark.basic_wxue_case
def test_one(self, account_data):
account_d = account_data.get_flasker_tb_one(result_mode='one', id=1)
print ('**************account.text=***************' + account_d.text)
assert 0




[flaskr.py]
import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
import pytest
from flasker.kernel.database_operator import DataBaseOperator
from flasker.models.account import FlaskerTbOne

DB_MODELS_PATH = 'untitled3/flasker/models/{}.py'

app = Flask(__name__)

def get_db():
db = getattr(g,'_database',None)
if db is None:
db = DataBaseOperator(DB_MODELS_PATH.format('account'))
g._database = db # 存入Flask.g对象中
return db

@app.before_request
def before_request():
get_db()

@app.route('/')
def show_entries():
#account_d = db.session_provider.query(FlaskerTbOne).all()
account_d = g._database.get_flasker_tb_one(result_mode='all')
entries = [dict(title=row.title, text=row.text) for row in account_d]
return render_template('show_entries.html', entries=entries)


@app.route('/add', methods=['POST'])
def add_entry():
if not session.get('logged_in'):
abort(401)
g._database.add_flasker_tb_one(title=request.form['title'], text=request.form['text'])
flash('New entry was successfully posted')
return redirect(url_for('show_entries'))

@app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
flash('You were logged in ')
return redirect(url_for('show_entries'))
return render_template('login.html', error=error)

@app.route('/logout')
def logout():
session.pop('logged_in', None)
flash('You were logged out')
return redirect(url_for('show_entries'))

app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

if __name__ == '__main__':

app.debug = True
app.config.from_object('settings.FlaskSetting')
app.run()



[settings.py]


class FlaskSetting:
USERNAME = 'admin'
PASSWORD = '123'









猜你喜欢

转载自www.cnblogs.com/suren2017/p/10875801.html