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

在上一篇博客中,我们完成了考勤系统的基本功能。现在,让我们继续开发请假系统。

十一 构建事件种类

还记得我们之前建立的考勤事件么?在当前的设计中,考勤事件有两个字段:事件代码和事件名称,现在我们决定给考勤事件增加一个种类的字段,来表明该事件属于何种事件。

我们需要建立一个新表来存储考勤事件的种类,就叫它TimeSheetEventCategory吧。

在database目录下建立tbltimesheeteventcategory.py,输入以下代码:

# database/tbltimesheeteventcategory.py

from database.tablebase import Base
from sqlalchemy import Column,String,Integer,Date,Boolean


class TimeSheetEventCategory(Base):
    __tablename__ = 'timesheeteventcategory'
    id = Column(Integer,autoincrement=True,primary_key=True)
    # 类别名称
    eventcategoryname = Column(String,unique=True,nullable=False)
    # 创建时间
    createdate = Column(Date,nullable=False)

    def __repr__(self):
        return '<timesheeteventcategory(eventcategoryname=%s)>' % (self.eventcategoryname)

该表很简单,只有三个字段:内部编号id,类别名称eventcategoryname和创建时间createdate。

进入migrate目录下,在powershell输入以下命令:

alembic revision -m "add timesheeteventcategory"

在新生成的py文件中,编写upgrade函数:

def upgrade():
    op.create_table(
        'timesheeteventcategory',
        sa.Column('id', sa.Integer, primary_key=True, autoincrement=True),
        sa.Column('eventcategoryname', sa.String, nullable=False),
        sa.Column('createdate', sa.Date, nullable=False),
    )

然后运行以下命令,完成建表。 

alembic upgrade head

接下来,让我们开始编写创建事件类别的后端部分。打开util/timesheet/timesheetutil.py,实现createtimesheeteventcategory函数:

# util/timesheet/timesheetutil.py
# ...
from database.tbltimesheeteventcategory import TimeSheetEventCategory

def createtimesheeteventcategory(categoryname):
    timesheeteventcategory = session.query(TimeSheetEventCategory).filter(TimeSheetEventCategory.eventcategoryname == categoryname)
    result = 'Fail'
    if type(timesheeteventcategory) is not TimeSheetEventCategory:
        newtimesheeteventcategory = TimeSheetEventCategory(eventcategoryname=categoryname,createdate=datetime.date.today())
        result = insertdata(newtimesheeteventcategory)
    return result

然后,在apps/timesheet_app/timesheet_app.py中实现CreateTimeSheetEventCategory:

# apps/timesheet_app/timesheet_app.py
# ...
from database.tbltimesheeteventcategory import TimeSheetEventCategory
from util.timesheet.timesheetutil import createtimesheeteventcategory

class CreateTimeSheetEventCategory(BaseHandler):
    def get(self):
        timesheeteventpath = gettemplatepath('createtimesheeteventcategory.html')
        timesheeteventcategorys = session.query(TimeSheetEventCategory)
        self.render(timesheeteventpath,timesheeteventcategorys=timesheeteventcategorys)

    def post(self):
        categoryname = self.get_argument('categoryname')
        result = createtimesheeteventcategory(categoryname)
        resultpath = gettemplatepath('result.html')
        if result == 'Fail':
            self.render(resultpath,result=result)
        else:
            self.redirect('/createtimesheeteventcategory')

# server/main.py
# ...
routelist = [
    # ...
    (r"/createtimesheeteventcategory", CreateTimeSheetEventCategory),
    # ...
]

这个页面的上半部分会显示出目前建立的事件类别,而底下会提供一个表单来建立新的事件类别,前端部分代码如下:

<!--createtimesheeteventcategory-->

{% 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="/">Home</a></li>
                            <li class="breadcrumb-item active">创建考勤事件类别</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">当前考勤事件类别</h4>
                                <div class="table-responsive">
                                    <table class="table">
                                        <thead>
                                            <tr>
                                                <th>#</th>
                                                <th>事件类别</th>
                                                <th>创建时间</th>
                                            </tr>
                                        </thead>
                                        <tbody>
                                            {% for category in timesheeteventcategorys %}
                                            <tr>
                                                <td>{{ category.id }}</td>
                                                <td>{{ escape(category.eventcategoryname) }}</td>
                                                <td>{{ category.createdate }}</td>
                                            </tr>
                                            {% end %}
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                            <div class="card-block">
                                <form class="form-horizontal form-material" action="/createtimesheeteventcategory" 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="categoryname" id="categoryname"/>
                                        </div>
                                    </div>
                                    <div class="form-group">
                                        <div class="col-sm-12">
                                            <button type="submit" class="btn btn-success">创建</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考勤系统
            </footer>
            <!-- ============================================================== -->
            <!-- End footer -->
            <!-- ============================================================== -->
        </div>
        {% end %}

效果如下:

从图中可知,我们建立了三个事件类别:Vacation、Work和Weekend,而在底下的表单中我们可以随时增加新的事件类别。

现在,让我们对之前的创建考勤事件功能做一些小改动,让考勤事件与类别相关联,并且也给已经建立好的考勤事件赋予类别。

首先别忘了给TimeSheetEvent添加eventcategory栏位,该栏位为String类型,这里不再赘述。

打开util/timesheet/timesheetutil.py,修改createtimesheetevent函数:

# util/timesheet/timesheetutil.py

# ...
def createtimesheetevent(eventcode,nickname,eventcategory):
    timesheetevent = session.query(TimeSheetEvent).filter(TimeSheetEvent.eventcode == eventcode).first()
    result = 'Fail'
    if type(timesheetevent) is not TimeSheetEvent:
        newtimesheetevent = TimeSheetEvent(eventcode=eventcode,nickname=nickname,eventcategory=eventcategory)
        result = insertdata(newtimesheetevent)
    # Modify by DS Liu 2021/1/23
    else:
        timesheetevent.eventcategory = eventcategory
        result = insertdata(timesheetevent)
    return result

这个函数和之前相比,多了eventcategory的参数;并且,当eventcode存在的时候,我们不是直接报错,而是给已有的事件加上eventcategory值。

在timesheet_app.py中的CreateTimeSheetEvent中也加入对应的代码:

# timesheet_app.py

class CreateTimeSheetEvent(BaseHandler):
    def get(self):
        timesheeteventpath = gettemplatepath('createtimesheetevent.html')
        timesheetevents = session.query(TimeSheetEvent)
        timesheeteventcategory = session.query(TimeSheetEventCategory)

        self.render(timesheeteventpath,timesheetevents=timesheetevents,timesheeteventcategorys=timesheeteventcategory)

    def post(self):
        eventcode = self.get_argument('eventcode')
        eventnickname = self.get_argument('eventnickname')
        eventcategory = self.get_argument('eventcategory')
        result = createtimesheetevent(eventcode,eventnickname,eventcategory)
        resultpath = gettemplatepath('result.html')
        if result == 'Fail':
            self.render(resultpath,result=result)
        else:
            self.redirect('/createtimesheetevent')

在get中,我们会获取所有的timesheeteventcategory并传入前端,以便用户选择;在post中,我们也会从表单中获取eventcategory的值传入util函数中。 

同样,在createtimesheetevent.html中添加一个下拉框,以便选择当前所有的事件类别。

 

<!--createtimesheetevent.html-->

<!-...-->
                                <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>
                                        <label class="col-md-12">类别 *</label>
                                        <div class="col-md-12">
                                            <select class="form-control form-control-line" name="eventcategory" id="eventcategory">
                                                {% for category in timesheeteventcategorys %}
                                                <option value="{{ category.eventcategoryname }}">{{ category.eventcategoryname }}</option>
                                                {% end %}
                                            </select>
                                        </div>
                                    </div>
                                    <div class="form-group">
                                        <div class="col-sm-12">
                                            <button type="submit" class="btn btn-success">创建/修改类别</button>
                                        </div>
                                    </div>
                                </form>
<!-...-->

这样,我们就完成了事件类别的相关工作,为请假系统打好了一个小基础。

十二 请假系统的数据库部分

我们的请假系统的成品如下图所示:

在表单中,可以选择请假的类别,在设定好开始时间和结束时间后,系统会自动算出一共请了多少天假,且最小单位是半天;在输入完请假原因后,点击创建即可创建请假申请。

现在,让我们先把所需的表建起来。目前我们只需要一张新表来管理假单,名为Vacation表。

在database目录下建立tblvacation.py文件,输入以下内容:

# database/tblvacation.py

from database.tablebase import Base
from sqlalchemy import Column,String,Integer,Date,Boolean

class Vacation(Base):
    __tablename__ = 'vacation'
    id = Column(Integer,autoincrement=True,primary_key=True)
    # 请假人
    username = Column(String,nullable=False)
    # 假期类别
    vacationcategory = Column(String,nullable=False)
    # 起始日期
    startdate = Column(Date,nullable=False)
    # 起始日期是否为上午
    startdateMorning = Column(Boolean,nullable=False)
    # 终止日期
    enddate = Column(Date,nullable=False)
    # 终止日期是否为上午
    enddateMorning = Column(Boolean,nullable=False)
    # 请假理由
    reason = Column(String,nullable=False)
    # 假期总时间
    timesum = Column(String,nullable=False)
    # 审批人
    approveuser = Column(String,nullable=False)
    # 审批日期
    approvedate = Column(Date,nullable=False)
    # 状态
    state = Column(String,nullable=False)
    # 提交日期
    applydate = Column(Date,nullable=False)


    def __repr__(self):
        return '<vacation(username=%s,vacationcategory=%s)>' % (self.username,self.vacationcategory)

然后再次输入熟悉的alembic升版命令:

alembic revison -m "add vacation table"

 在新生成的py文件中,改写其upgrade函数:

def upgrade():
    op.create_table(
        'vacation',
        sa.Column('id', sa.Integer, primary_key=True, autoincrement=True),
        sa.Column('username', sa.String, nullable=False),
        sa.Column('vacationcategory', sa.String, nullable=False),
        sa.Column('startdate', sa.Date,nullable=False),
        sa.Column('startdateMorning', sa.Boolean,nullable=False),
        sa.Column('enddate', sa.Date,nullable=False),
        sa.Column('enddateMorning', sa.Boolean,nullable=False),
        sa.Column('reason', sa.String, nullable=False)
        sa.Column('timesum', sa.String,nullable=False)
        sa.Column('approveuser',sa.String,nullable=False)
        sa.Column('approvedate', sa.Date, nullable=False)
        sa.Column('state', sa.String, nullable=False)
        sa.Column('applydate', sa.Date,nullable=False)

    )

然后执行upgrade命令,将vacation表建立完毕。此时,我们就完成了请假系统的数据库部分。

在这期博客中,我们实现了创建事件类别的功能,并且为已有的考勤事件添加了事件类别;此外,我们还展示了请假系统的界面,以及完成了vacation表的建立。在下一篇博客中,我将继续介绍请假系统的后端实现,希望大家继续关注~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值