日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

Tornado笔记——用Tornado搭建假单统计考勤系统(六)

發(fā)布時間:2023/12/20 windows 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tornado笔记——用Tornado搭建假单统计考勤系统(六) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這篇和上一篇博文隔的時間有點遠(yuǎn)了,希望大家還記得我們這個系統(tǒng)之前都做了什么。在上一篇博客中,我們構(gòu)造了一個復(fù)雜的表單和calendar類來實現(xiàn)填寫考勤的功能。現(xiàn)在,我們要實現(xiàn)查看考勤以及審批考勤的功能。

6 項目目錄結(jié)構(gòu)的調(diào)整

現(xiàn)在我們的項目已經(jīng)有了很多的RequestHandler,把這么多RequestHandler都放在一個main.py文件里會很不好管理,因此,我們需要對項目的結(jié)構(gòu)做一點調(diào)整,把這些RequestHandler按功能放到不同的目錄里。

調(diào)整后的目錄結(jié)構(gòu)如下:

?我們主要調(diào)整server目錄的結(jié)構(gòu):在server下新建一個名為apps的package,再在apps包中新建timesheet_app和user_app這兩個package,分別存放user和timesheet相關(guān)功能的RequestHandler。在timesheet_app包中新建timesheet_app.py,把如下RequestHandler從main.py中挪進(jìn)去:

timesheet_app中的RequestHandler
RequestHandler名稱對應(yīng)功能
TimeSheetIndex考勤
FillTimeSheet填寫考勤

在user_app包中新建user_app.py,把如下RequestHandler從main.py中挪進(jìn)去:

user_app中的RequestHandler
RequestHandler名稱對應(yīng)功能
Register注冊用戶
Login用戶登錄
CreateUserGroup創(chuàng)建用戶組
ViewUserGroup *查看用戶組
PersonalInfo *個人信息查看
UserManage *用戶管理
Approve *批準(zhǔn)用戶
LogOff *注銷用戶
LogOut *用戶登出

翻了翻前面的博客,發(fā)現(xiàn)帶*的功能還沒有寫到博客中,等我們將考勤部分寫的差不多了再來將這些功能補(bǔ)全。?

?最后,在apps包下建立basehandler.py,將我們的BaseHandler放進(jìn)去,大家可以自行補(bǔ)全timesheet_app.py、user_app.py和basehandler.py中的import部分。

這樣,我們的目錄結(jié)構(gòu)就調(diào)整完畢,main.py會變的簡潔很多,新的main.py代碼如下所示:

# server/main.py import sys import platform import os sys.path.append(os.path.abspath('..')) from setting.globalsettings import getconfig from util.users.userutil import hasinit, inituser import tornado.ioloop import tornado.web from server.apps.user_app.user_app import * from server.apps.timesheet_app.timesheet_app import * if platform.system() == 'Windows':import asyncioasyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())class Index(BaseHandler):def get(self):indexpath = gettemplatepath('index.html')self.render(indexpath)def make_app():routelist = [# 保持不變]return tornado.web.Application(routelist,cookie_secret='12f6352#527',autoreload=True,debug=True,template_path='D:\\LeaveManage\\server\\template')if __name__ == '__main__':init_result = hasinit()if init_result == False:result = inituser()if result == 'Fail':print('初始化網(wǎng)站失敗!')exit(0)app = make_app()port = int(getconfig('PORT'))app.listen(port)print('系統(tǒng)啟動')tornado.ioloop.IOLoop.current().start()

這里注意,當(dāng)我們建立Application時,我們要指定template_path到我們的template目錄,否則在調(diào)整完目錄結(jié)構(gòu)后,tornado不會找到這個目錄而是按RequestHandler所在目錄去尋找模板文件,那樣肯定找不到。

現(xiàn)在,我們可以繼續(xù)往下進(jìn)行了,實現(xiàn)查看考勤以及批準(zhǔn)考勤的功能。

7 創(chuàng)建考勤事件

在實現(xiàn)查看考勤之前,讓我們先實現(xiàn)另一個小功能——創(chuàng)建考勤事件。通過這個功能,可以讓我們添加不同的考勤事件,如工作、病假、調(diào)休等,以供在之前的填寫考勤功能中選擇。

該功能的頁面如下:

這個頁面十分簡單, 上半部分列出現(xiàn)有的考勤事件,下半部分的表單用于建立新的表單事件。事件名即上半部分的事件代碼,是事件真正存在DB中的值,而事件別名是用于查看考勤時顯示出的事件名稱。

我們在timesheetutil.py中編寫createtimesheetevent函數(shù),用于生成考勤事件:

# timesheetutil.py # ... from database.tbltimesheetevent import TimeSheetEvent def createtimesheetevent(eventcode,nickname):timesheetevent = session.query(TimeSheetEvent).filter(TimeSheetEvent.eventcode == eventcode)result = 'Fail'if type(timesheetevent) is not TimeSheetEvent:newtimesheetevent = TimeSheetEvent(eventcode=eventcode,nickname=nickname)result = insertdata(newtimesheetevent)return result

這個小函數(shù)沒啥說的,根據(jù)eventcode查一下是否有考勤事件存在,如果沒有的話則創(chuàng)建之。

然后,我們在timesheet_app.py實現(xiàn)CreateTimeSheetEvent RequestHandler:

# timesheet_app.pyclass CreateTimeSheetEvent(BaseHandler):def get(self):timesheeteventpath = gettemplatepath('createtimesheetevent.html')timesheetevents = session.query(TimeSheetEvent)self.render(timesheeteventpath,timesheetevents=timesheetevents)def post(self):eventcode = self.get_argument('eventcode')eventnickname = self.get_argument('eventnickname')result = createtimesheetevent(eventcode,eventnickname)resultpath = gettemplatepath('result.html')if result == 'Fail':self.render(resultpath,result=result)else:self.redirect('/createtimesheetevent')# main.py # ... routelist = [# ...(r"/createtimesheetevent",CreateTimeSheetEvent),# ... ] # ...

這個頁面也沒什么說的,常規(guī)的抓取數(shù)據(jù)后顯示/插入,不要忘了在main.py中注冊其路由。

前端頁面createtimesheetevent.html的block塊代碼如下:

<!--createtimesheetevent.html-->{% block content %}<div class="page-wrapper"><!-- ============================================================== --><!-- Container fluid --><!-- ============================================================== --><div class="container-fluid"><!-- ============================================================== --><!-- Bread crumb and right sidebar toggle --><!-- ============================================================== --><div class="row page-titles"><div class="col-md-6 col-8 align-self-center"><h3 class="text-themecolor m-b-0 m-t-0">創(chuàng)建考勤事件</h3><ol class="breadcrumb"><li class="breadcrumb-item"><a href="/">Home</a></li><li class="breadcrumb-item active">創(chuàng)建考勤事件</li></ol></div></div><!-- ============================================================== --><!-- End Bread crumb and right sidebar toggle --><!-- ============================================================== --><!-- ============================================================== --><!-- Start Page Content --><!-- ============================================================== --><!-- Row --><div class="row"><!-- Column --><div class="col-lg-8 col-xlg-9 col-md-7"><div class="card"><div class="card-block"><h4 class="card-title">當(dāng)前考勤事件</h4><div class="table-responsive"><table class="table"><thead><tr><th>#</th><th>事件代碼</th><th>事件別名</th></tr></thead><tbody>{% for event in timesheetevents %}<tr><td>{{ event.id }}</td><td>{{ escape(event.eventcode) }}</td><td>{{ escape(event.nickname) }}</td></tr>{% end %}</tbody></table></div></div><div class="card-block"><form class="form-horizontal form-material" action="/createtimesheetevent" method="post" ><div class="form-group"><label class="col-md-12">事件名 *</label><div class="col-md-12"><input type="text" class="form-control form-control-line" required=true name="eventcode" id="eventcode"></div><label class="col-md-12">別名 *</label><div class="col-md-12"><input type="text" class="form-control form-control-line" required=true name="eventnickname" id="eventnickname"></div></div><div class="form-group"><div class="col-sm-12"><button type="submit" class="btn btn-success">創(chuàng)建</button></div></div></form></div></div></div><!-- Column --></div><!-- Row --><!-- ============================================================== --><!-- End PAge Content --><!-- ============================================================== --></div><!-- ============================================================== --><!-- End Container fluid --><!-- ============================================================== --><!-- ============================================================== --><!-- footer --><!-- ============================================================== --><footer class="footer text-center">? 2020 Tornado考勤系統(tǒng)</footer><!-- ============================================================== --><!-- End footer --><!-- ============================================================== --></div>{% end %}

在實現(xiàn)了這個功能后,我們就可以按照上圖所示將我們的考勤事件建立起來,以便在之后的查看考勤功能中使用。

8 查看考勤

在準(zhǔn)備好了考勤事件后,我們就可以實現(xiàn)查看考勤功能了。我們需要實現(xiàn)一個TimeSheetViewer類,這個類會返回一個key為日期value為事件別名的字典,與之前的Calendar類配合可以讓我們查看用戶填寫的考勤結(jié)果。

打開timesheetutil.py,實現(xiàn)TimeSheetViewer類:

# timesheetutil.pyclass TimeSheetViewer:def __init__(self,username,year,month):self.__username = usernameself.__year = yearself.__month = monthself.__timesheetmap = {}self.__state = ''self.__approveuser = ''self.__approvedate = ''def __gettimesheetinfo(self):timesheet = session.query(TimeSheet).filter(and_(TimeSheet.username == self.__username,TimeSheet.year == self.__year, TimeSheet.month == self.__month)).first()timecalendar = TimeSheetCalendar(self.__year,self.__month)timecalendar.generatecalendar()monthmap = timecalendar.getmonthmap()print(type(timesheet))if type(timesheet) is TimeSheet:self.__state = timesheet.stateself.__approveuser = timesheet.approveusernameself.__approvedate = timesheet.approvedatefor days in monthmap:tmpday = int(days.split('-')[2])tmpmonth = int(days.split('-')[1])dayinfo = 'day' + str(tmpday)if tmpmonth == self.__month:event = session.query(TimeSheetEvent).filter(TimeSheetEvent.eventcode == getattr(timesheet,dayinfo,'')).first()if type(event) is TimeSheetEvent:self.__timesheetmap[days] = event.nicknameelse:self.__timesheetmap[days] = 'N/A'else:self.__timesheetmap[days] = 'N/A'else:for days in monthmap:self.__timesheetmap[days] = 'N/A'def gettimesheetmap(self):self.__gettimesheetinfo()return self.__timesheetmapdef getstate(self):return self.__statedef getapproveuser(self):return self.__approveuserdef getapprovedate(self):return self.__approvedate

先看看這個類中的參數(shù)介紹:

  • __username:用戶名
  • __year:年
  • __month:月
  • __timesheetmap:最終返回的結(jié)果,key為日期value為事件別名的字典
  • __state:考勤表狀態(tài)
  • __approveuser:批準(zhǔn)的用戶
  • __approvedate:批準(zhǔn)日期

這個類的核心函數(shù)為__gettimesheetinfo。在這個函數(shù)中,首先通過year和month參數(shù)從TimeSheet表中拿到此月的數(shù)據(jù),再調(diào)用之前的Calendar類獲得此月的monthmap。然后,從TimeSheet中獲得考勤表的狀態(tài)、批準(zhǔn)的用戶以及批準(zhǔn)日期,再按日期去獲得每天的考勤事件;如果某個日期的考勤事件不存在,則用N/A代替。這樣,我們就得到了一個key為日期value為事件別名的字典,以及拿到了考勤表的狀態(tài)、批準(zhǔn)用戶以及批準(zhǔn)日期。底下的幾個getter函數(shù)就不再贅述了。

我們打開timesheet_app.py,實現(xiàn)ViewTimeSheet:

# timesheet_app.pyclass ViewTimeSheet(BaseHandler):def get(self,year,month):username = ''bytes_user = self.get_secure_cookie('currentuser')if type(bytes_user) is bytes:username = str(bytes_user, encoding='utf-8')year = int(year.split('=')[1])month = int(month.split('=')[1])timesheetviewer = TimeSheetViewer(username=username,year=year,month=month)timesheetviewer.gettimesheetmap()timesheetcalendar = TimeSheetCalendar(year, month)timesheetcalendar.generatecalendar()monthday_map = timesheetcalendar.getmonthmap()week_list = timesheetcalendar.getweeklist()timesheet_map = timesheetviewer.gettimesheetmap()timesheet_state = timesheetviewer.getstate()timesheet_approveuser = timesheetviewer.getapproveuser()timesheet_approvedate = timesheetviewer.getapprovedate()viewtimesheetpath = gettemplatepath('viewtimesheet.html')self.render(viewtimesheetpath, monthdaymap=monthday_map,weeklist=week_list,timesheetmap=timesheet_map,timesheetstate=timesheet_state,timesheetapprovedate=timesheet_approvedate,timesheetapproveuser=timesheet_approveuser)# main.py # ... routelist = [# ...(r"/viewtimesheet/(year=\d*)&(month=\d*)",ViewTimeSheet),# ... ] # ...

這個頁面和之前的FillTimeSheet大致一樣,只不過多調(diào)用了新寫的TimeSheetViewer類,以及將其結(jié)果作為參數(shù)傳入render函數(shù)中。依舊不要忘記在main.py中注冊路由。

viewtimesheet.html的block塊如下:

<!--viewtimesheet.html-->{% block content %}<div class="page-wrapper"><!-- ============================================================== --><!-- Container fluid --><!-- ============================================================== --><div class="container-fluid"><!-- ============================================================== --><!-- Bread crumb and right sidebar toggle --><!-- ============================================================== --><div class="row page-titles"><div class="col-md-6 col-8 align-self-center"><h3 class="text-themecolor m-b-0 m-t-0">查看考勤</h3><ol class="breadcrumb"><li class="breadcrumb-item"><a href="/timesheetindex">考勤</a></li><li class="breadcrumb-item active">查看考勤</li></ol></div></div><!-- ============================================================== --><!-- End Bread crumb and right sidebar toggle --><!-- ============================================================== --><!-- ============================================================== --><!-- Start Page Content --><!-- ============================================================== --><div class="row"><!-- column --><div class="col-sm-12"><div class="card"><div class="card-block"><h4 class="card-title">查看考勤</h4><div class="table-responsive">{% for week in weeklist %}<table class="table"><thead><tr>{% for day in week %}<th>{{ day }}{% if monthdaymap[day] == 'Mon' or monthdaymap[day] == 'Tues' or monthdaymap[day] == 'Wed' or monthdaymap[day] == 'Thur' or monthdaymap[day] == 'Fri' or monthdaymap[day] == 'Sat' or monthdaymap[day] == 'Sun' %}({{ monthdaymap[day] }}){% else %}(N/A){% end %}</th>{% end %}</tr></thead><tbody><tr>{% for day in week %}<td>{{ timesheetmap[day] }}</td>{% end %}</tr></tbody></table>{% end %}<table class="table"><thead><tr><th>狀態(tài)</th><th>審批人</th><th>審批日期</th></tr></thead><tbody><tr><td>{{ timesheetstate }}</td><td>{{ timesheetapproveuser }}</td><td>{{ timesheetapprovedate }}</td></tr></tbody></table></div></div></div></div></div><!-- ============================================================== --><!-- End PAge Content --><!-- ============================================================== --></div><!-- ============================================================== --><!-- End Container fluid --><!-- ============================================================== --><!-- ============================================================== --><!-- footer --><!-- ============================================================== --><footer class="footer text-center">? 2020 Tornado考勤系統(tǒng)</footer><!-- ============================================================== --><!-- End footer --><!-- ============================================================== --></div>{% end %}

這個頁面同樣和填寫考勤的頁面很相似,只不過是把每周日期下的內(nèi)容從下拉表單變?yōu)榱藢嶋H填寫的結(jié)果,并且在底下新增了一個表格用于顯示審批狀態(tài)、審批人以及審批日期。

效果如下所示,在日期下方顯示了填寫的考勤項,最下面顯示考勤狀態(tài)和審批人。

在這篇博客中,我們對項目結(jié)構(gòu)進(jìn)行了一番調(diào)整,將各類功能分門別類放到不同的包中,使得main.py文件相比以前大為簡潔;實現(xiàn)了一個簡單的小功能——創(chuàng)建考勤事件,這使得我們可以將考勤事件按照別名顯示出來;最后,我們實現(xiàn)了一個TimeSheetViewer類用于生成日期-考勤的map,并構(gòu)造頁面將其顯示出來,同時顯示考勤審批的狀態(tài)。

在下一篇博客中,我們將繼續(xù)實現(xiàn)真正的審批功能,希望大家繼續(xù)關(guān)注~

總結(jié)

以上是生活随笔為你收集整理的Tornado笔记——用Tornado搭建假单统计考勤系统(六)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。