曾經,由於對 sqlalchemy 不熟悉,執拗的拋棄之,直接引入原生的 cx_Oracle 來生成報表,可是通過一堆的「上下文等」錯誤後,我幡然悔悟,仍是回到了 sqlalchemy 的懷抱來。
認真學習 sqlalchemy,你會發現意想不到的驚喜。本文主要講解如何生成不一樣需求的報表。
不在贅述。詳情請下載代碼查看。html
第一個頁面使用sqlalchemy查詢比較簡單,關鍵點是:git
views.py
內容:github
@show.route('/01', methods = ['GET', 'POST']) @login_required def _01(): g1 = aliased(OusiGuest) # 重複用到該數據庫,須要設置別名。 g2 = aliased(OusiGuest) # 重複用到該數據庫,須要設置別名。 page = request.args.get('page', 1, type=int) # 分頁 if current_user.role == 'admin': # 區分權限 database = db.session.query(OusiStaff.department, OusiStaff.name.label('staff_name'), OusiStaff.phone, OusiStaff.role, g1.name.label('guest_name'), g1.month, g1.balance, func.nvl(db.session.query(g2.balance).filter( g1.name == g2.name, func.to_date(g2.month, 'yyyy-mm') == func.add_months( func.to_date(g1.month, 'yyyy-mm'), -1) ), 0).label('last_balance') ).filter( OusiStaff.phone == g1.staff_phone, current_user.department == OusiStaff.department, g1.month == date.today().strftime('%Y-%m') ).order_by(g1.name).group_by(OusiStaff.department, OusiStaff.name.label('staff_name'), OusiStaff.phone, OusiStaff.role, g1.name.label('guest_name'), g1.month, g1.balance) else: database = db.session.query(OusiStaff.department, OusiStaff.name.label('staff_name'), OusiStaff.phone, OusiStaff.role, g1.name.label('guest_name'), g1.month, g1.balance, func.nvl(db.session.query(g2.balance).filter( g1.name==g2.name, func.to_date(g2.month, 'yyyy-mm')==func.add_months( func.to_date(g1.month, 'yyyy-mm'), -1) ), 0).label('last_balance') ).filter( OusiStaff.phone==g1.staff_phone, current_user.phone==g1.staff_phone, g1.month==date.today().strftime('%Y-%m') ).order_by(g1.name).group_by(OusiStaff.department, OusiStaff.name.label('staff_name'), OusiStaff.phone, OusiStaff.role, g1.name.label('guest_name'), g1.month, g1.balance) data = database.paginate(page, per_page=current_app.config['OUSI_POSTS_PER_PAGE'], error_out=False) return render_template('show/01.html', data=data)
其實,以上內容就是利用 sqlalchemy 的聯表查詢問題,將 OusiStaff 和 OusiGuest 以 phone 值爲關聯進行查詢,而後將結果顯示出來。sql
其中的難點一是利用 func.to_date
和 func.add_months
對上個月這個時間進行關聯查詢(凡是數據庫支持的函數,在 sqlalchemy 中均可以使用 func 加函數名來操做。),二是利用 func.nvl
函數來對初始化數據進行賦值 0 的操做。 具體的 sqlalchemy 語法,請參見代碼。數據庫
提示:
注意 sqlalchemy 的語法。func.nvl(db.session.query(g2.balance).filter(g1.name==g2.name, func.to_date(g2.month, 'yyyy-mm')==func.add_months(func.to_date(g1.month, 'yyyy-mm'), -1)), 0).label('last_balance')
,這語句的主要是爲了實現查詢上個月的餘額,若是查詢不到,經過 oracle 的 nvl 函數設置爲 0 。
權限爲 admin 的用戶顯示本部門下全部員工的相關信息。flask
權限爲 general 的用戶只顯示本人的相關信息。session
第二頁使用 sqlalchemy 查詢稍微複雜點,關鍵點除了第一個頁面的要求外還有:oracle
views.py
內容:app
@show.route('/02', methods = ['GET', 'POST']) @login_required def _02(): page = request.args.get('page', 1, type=int) g1 = aliased(OusiGuest) g2 = aliased(OusiGuest) if current_user.role == 'admin': sbq = db.session.query(OusiStaff.department, OusiStaff.role, OusiStaff.name.label('staff_name'), g1.staff_phone, g1.name.label('guest_name'), g1.month, g1.balance, func.nvl(db.session.query(g2.balance).filter( g1.name==g2.name, func.add_months(func.to_date(g1.month, 'yyyy-mm'), -1) == func.to_date(g2.month, 'yyyy-mm') ), 0).label('last_balance')).filter( OusiStaff.phone==g1.staff_phone, OusiStaff.department==current_user.department ).group_by(OusiStaff.department, OusiStaff.role, OusiStaff.name.label('staff_name'), g1.staff_phone, g1.name.label('guest_name'), g1.month, g1.balance).subquery() database = db.session.query(sbq.c.department, sbq.c.role, sbq.c.staff_name, sbq.c.staff_phone, sbq.c.month, func.count(sbq.c.guest_name).label('members'), func.sum(sbq.c.balance).label('balance'), func.sum(sbq.c.last_balance).label('last_balance')).\ filter(sbq.c.month==date.today().strftime('%Y-%m')).group_by(sbq.c.department, sbq.c.role, sbq.c.staff_name, sbq.c.staff_phone, sbq.c.month) else: sbq = db.session.query(OusiStaff.department, OusiStaff.role, OusiStaff.name.label('staff_name'), g1.staff_phone, g1.name.label('guest_name'), g1.month, g1.balance, func.nvl(db.session.query(g2.balance).filter( g1.name == g2.name, func.add_months(func.to_date(g1.month, 'yyyy-mm'), -1) == func.to_date(g2.month, 'yyyy-mm') ), 0).label('last_balance')).filter( OusiStaff.phone == g1.staff_phone, OusiStaff.phone == current_user.phone ).group_by(OusiStaff.department, OusiStaff.role, OusiStaff.name.label('staff_name'), g1.staff_phone, g1.name.label('guest_name'), g1.month, g1.balance).subquery() database = db.session.query(sbq.c.department, sbq.c.role, sbq.c.staff_name, sbq.c.staff_phone, sbq.c.month, func.count(sbq.c.guest_name).label('members'), func.sum(sbq.c.balance).label('balance'), func.sum(sbq.c.last_balance).label('last_balance')). \ filter(sbq.c.month == date.today().strftime('%Y-%m')).group_by(sbq.c.department, sbq.c.role, sbq.c.staff_name, sbq.c.staff_phone, sbq.c.month) data = database.paginate(page, per_page=current_app.config['OUSI_POSTS_PER_PAGE'], error_out=False) return render_template('show/02.html', data=data)
注意 query 的字段以及 group_by 裏分組查詢的字段。函數
權限爲 admin 的用戶顯示本部門下全部員工的相關信息。
權限爲 general 的用戶只顯示本人的相關信息。
下節更精彩,將實現搜索查詢功能,又是一堆 sqlalchemy 語句。