基于 oracle 的 flask 項目(三)——生成報表

曾經(jīng)秤茅,因為對 sqlalchemy 不熟悉彻秆,固執(zhí)的拋棄之懈词,直接引入原生的 cx_Oracle 來生成報表窃躲,但是經(jīng)過一堆的“上下文等”錯誤后,我幡然悔悟钦睡,還是回到了 sqlalchemy 的懷抱來蒂窒。
認真學習 sqlalchemy躁倒,你會發(fā)現(xiàn)意想不到的驚喜。本文主要講解如何生成不同需求的報表洒琢。

項目描述

  • 第一個頁面秧秉,以 OusiStaff.phone 和 OusiGuest.staff_phone 為關聯(lián),查詢出本月職工的關聯(lián)客戶及客戶的資產(chǎn)余額衰抑。
  • 第二個頁面象迎,以 OusiStaff.phone 和 OusiGuest.staff_phone 為關聯(lián),查詢出每個職工所有關聯(lián)的客戶的本月資產(chǎn)呛踊、上月資產(chǎn)及本月管戶資產(chǎn)增額砾淌。
  • 具有管理員權限的員工可以看到本部門下面所有員工的相關信息,非管理員權限的員工只能查看自己的相關信息谭网。
  • 查詢功能留給下一章詳細講解汪厨。

建立報表模板

不在贅述。詳情請下載代碼查看愉择。

實現(xiàn)第一個頁面

建立第一個頁面的試圖函數(shù)

第一個頁面使用sqlalchemy查詢比較簡單劫乱,關鍵點是:

  • 區(qū)分權限。
  • 聯(lián)表查詢锥涕。
  • 建立上個月的虛字段衷戈。
  • 分頁顯示。
  • 查詢嵌套层坠。

views.py 內(nèi)容:

@show.route('/01', methods = ['GET', 'POST'])
@login_required
def _01():
    g1 = aliased(OusiGuest) # 重復用到該數(shù)據(jù)庫殖妇,需要設置別名。
    g2 = aliased(OusiGuest) # 重復用到該數(shù)據(jù)庫破花,需要設置別名谦趣。
    page = request.args.get('page', 1, type=int) # 分頁
    if current_user.role == 'admin': # 區(qū)分權限
        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)

其實,以上內(nèi)容就是利用 sqlalchemy 的聯(lián)表查詢問題旧乞,將 OusiStaff 和 OusiGuest 以 phone 值為關聯(lián)進行查詢蔚润,然后將結(jié)果顯示出來。

其中的難點一是利用 func.to_datefunc.add_months 對上個月這個時間進行關聯(lián)查詢(凡是數(shù)據(jù)庫支持的函數(shù)尺栖,在 sqlalchemy 中都可以使用 func 加函數(shù)名來操作嫡纠。),二是利用 func.nvl 函數(shù)來對初始化數(shù)據(jù)進行賦值 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') 者蠕,這語句的主要是為了實現(xiàn)查詢上個月的余額,如果查詢不到掐松,通過 oracle 的 nvl 函數(shù)設置為 0 踱侣。

第一個頁面顯示結(jié)果

權限為 admin 的用戶顯示本部門下所有員工的相關信息粪小。

012.png

權限為 general 的用戶只顯示本人的相關信息。

013.png

實現(xiàn)第二個頁面

建立第二個頁面的試圖函數(shù)

第二頁使用 sqlalchemy 查詢稍微復雜點抡句,關鍵點除了第一個頁面的要求外還有:

  • 使用 func.sum 對相關字段進行相加運算探膊。
  • 用到了子查詢。

views.py 內(nèi)容:

@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 里分組查詢的字段待榔。

第二個頁面顯示結(jié)果

權限為 admin 的用戶顯示本部門下所有員工的相關信息逞壁。

014.png

權限為 general 的用戶只顯示本人的相關信息。

015.png

源碼下載

下節(jié)更精彩锐锣,將實現(xiàn)搜索查詢功能腌闯,又是一堆 sqlalchemy 語句。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雕憔,一起剝皮案震驚了整個濱河市姿骏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌橘茉,老刑警劉巖工腋,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姨丈,死亡現(xiàn)場離奇詭異畅卓,居然都是意外死亡,警方通過查閱死者的電腦和手機蟋恬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門翁潘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人歼争,你說我怎么就攤上這事拜马。” “怎么了沐绒?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵俩莽,是天一觀的道長。 經(jīng)常有香客問我乔遮,道長扮超,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任蹋肮,我火速辦了婚禮出刷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坯辩。我一直安慰自己馁龟,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布漆魔。 她就那樣靜靜地躺著坷檩,像睡著了一般却音。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矢炼,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天僧家,我揣著相機與錄音,去河邊找鬼裸删。 笑死八拱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的涯塔。 我是一名探鬼主播肌稻,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼匕荸!你這毒婦竟也來了爹谭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤榛搔,失蹤者是張志新(化名)和其女友劉穎诺凡,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體践惑,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡腹泌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了尔觉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凉袱。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖侦铜,靈堂內(nèi)的尸體忽然破棺而出专甩,到底是詐尸還是另有隱情,我是刑警寧澤钉稍,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布涤躲,位于F島的核電站,受9級特大地震影響贡未,放射性物質(zhì)發(fā)生泄漏种樱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一羞秤、第九天 我趴在偏房一處隱蔽的房頂上張望缸托。 院中可真熱鬧,春花似錦瘾蛋、人聲如沸俐镐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佩抹。三九已至叼风,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間棍苹,已是汗流浹背无宿。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留枢里,地道東北人孽鸡。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像栏豺,于是被迫代替她去往敵國和親彬碱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載奥洼,覺得這篇寫 SQLAlchemy Core巷疼,寫得非常不錯。不過后續(xù)他沒寫SQLAlchemy ORM... ...
    非夢nj閱讀 5,414評論 1 14
  • 22年12月更新:個人網(wǎng)站關停灵奖,如果仍舊對舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,184評論 22 257
  • 2016年瓷患,最火爆的概念無疑是出自馬云之口的“新零售”骡尽。這一概念堪稱對線上線下企業(yè)的同步顛覆性創(chuàng)新。 那什么是新零...
    冬天的一把火i閱讀 210評論 0 0
  • 小時候的夢想是長大了能夠賺很多很多的錢 讓父母過上不那么辛苦的日子 給她們在縣城買套房子 希望她們在親戚面前 可以...
    滄海因果LH7閱讀 219評論 0 0
  • 每日一書 笑話一則 夏天坐公交 夏天坐公交可以用一副對聯(lián)來形容: 上聯(lián):不管男的女的老的少的高的矮的胖的瘦的千眾集...
    有趣文叔閱讀 173評論 0 2