【华为云技术分享】用Flask开发Web版日历应用
Python Calender模块
python的日历模块Calender提供了多种日历展示模式:
参数 | 说明 | 示例 |
---|---|---|
calendar.calendar(year) | 输出某一年的日历 | calendar.calendar(2019) |
monthcalendar(year, month) | 返回一个月中天数列表(不是当前月份的天数为0) | calendar.monthcalendar(2019, 6) |
setfirstweekday(firstweekday) | 0是星期一,…,6为星期日 | calendar.setfirstweekday(firstweekday=6) |
prmonth(theyear, themonth, w=0, l=0) | w每个单元格宽度,l每列换l行 | calendar.prmonth(2019, 6) |
calendar.month_abbr[month] | 打印月份对应的英文简写 | calendar.month_abbr[6] |
calendar.isleap(year) | 判断某一年是否为闰年 | calendar.isleap(2012) |
calendar.weekday(year,month,day) | 判断某一天是周几0(周一一)到6(周日) | calendar.weekday(2019,12,25) |
… | … | … |
基本的就是上面这些了….
Bootstrap 表格
Flask使用Bootstrap模板,这个前几期已经说了,还不清楚的朋友,可以看看往期内容。
今天主要说下Bootstrap的table
类 | 说明 |
---|---|
.table | 少量的内补(padding)和水平方向的分隔线 |
.table-striped | 给 <tbody> 之内的每一行增加斑马条纹样式 |
.table-bordered | 为表格和其中的每个单元格增加边框 |
.table-hover | 可以让 <tbody> 中的每一行对鼠标悬停状态作出响应 |
.table-condensed | 可以让表格更加紧凑,单元格中的内补(padding)均会减半 |
.active | 鼠标悬停在行或单元格上时所设置的颜色 |
.success | 标识成功或积极的动作 |
.info | 标识普通的提示信息或动作 |
.warning | 标识警告或需要用户注意 |
.danger | 标识危险或潜在的带来负面影响的动作 |
Flask日历
今天通过Flask,制作一个网页版日历,系统启动后,计算当天日期,并生成日历,高亮表示本月和今日。
首先,需要考虑日历的响应式布局,每行放四个月的数据,所以需要使用Bootstrap的栅格化<div class="col-lg-3">
,保证在没有足够宽的情况下,自动转为单月的数据展示,避免重叠
其次,针对数据的排列,日历模块中calendar.monthcalendar(year, month)
会返回一个原组,但如同下面的情况:
1 1>>> import calendar 2 2>>> calendar.setfirstweekday(firstweekday=6) 3 3>>> calendar.monthcalendar(2019,5) 4 4>>> [[0, 0, 0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], 5 5 [12, 13, 14, 15, 16, 17, 18], [19, 20, 21, 22, 23, 24, 25], 6 6 [26, 27, 28, 29, 30, 31, 0]] 7 7>>> calendar.monthcalendar(2019,6) 8 8>>> [[0, 0, 0, 0, 0, 0, 1], [2, 3, 4, 5, 6, 7, 8], 9 9 [9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22], 10 10 [23, 24, 25, 26, 27, 28, 29], [30, 0, 0, 0, 0, 0, 0]] 11 11>>> len(calendar.monthcalendar(2019,5)) 12 12>>> 5 13 13>>> len(calendar.monthcalendar(2019,6)) 14 14>>> 6
有的月份刚好卡在1号周六,所以列表长为6….这样会导致绘图的时候日历表格高度差异,所以如果不满6个的月份,我们手动给他创建创建一个数据全为0的空列表:
1 1def calc_calender(date): 2 2 year = date.year 3 3 yearInfo = dict() 4 4 for month in range(1, 13): 5 5 days = calendar.monthcalendar(year, month) 6 6 if len(days) != 6: 7 7 days.append([0 for _ in range(7)]) 8 8 month_addr = calendar.month_abbr[month] 9 9 yearInfo[month_addr] = days 10 10 return yearInfo
针对返回的数据,使用Jinjia2模板进行循环获取,要注意一点是,如果是日期是0的,代表站位符,需要进行替换。
但如果整行都是零,会导致Bootstrap的表单样式变更,故使用 
进行占位操作。
最终HTML代码如下:
1 1<!DOCTYPE html> 2 2<html lang="en"> 3 3 4 4<head> 5 5 <meta charset="utf-8"> 6 6 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7 7 <meta name="viewport" content="width=device-width, initial-scale=1"> 8 8 <title>Flask Calendar</title> 9 9 <link rel="icon" href="{{ url_for('static',filename='favicon.ico') }}"> 10 10 <link href="{{ url_for('static',filename='bootstrap.min.css') }}" rel="stylesheet"> 11 11</head> 12 12 13 13<body> 14 14<div class="container"> 15 15 <h3 class="text-center">Welcome to Flask Calendar {{date.year}} <small><a href="https://www.jianshu.com/u/d23fd5012bed"> 清风Python</a></small></h3> 16 16 17 17 {% set week_addr = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] %} 18 18 {% for month_addr,monthInfo in content.items()%} 19 19 20 20 <div class="col-lg-3"> 21 21 <h4 class="text-center">{{month_addr}}</h4> 22 22 {% with _month=false %} 23 23 {% if month_addr == this_month %} 24 24 <table style='background-color:#a6e1ec' class="table table-bordered"> 25 25 {% set _month = true %} 26 26 {% else %} 27 27 <table class="table table-bordered"> 28 28 {% endif %} 29 29 <tr> 30 30 {% for addr in week_addr %} 31 31 <th>{{addr}}</th> 32 32 {% endfor %} 33 33 </tr> 34 34 {% for weeks in monthInfo %} 35 35 <tr> 36 36 {% for day in weeks %} 37 37 {% if day == 0 %} 38 38 <td> </td> 39 39 {% elif _month== true and day == date.day %} 40 40 <td style="background-color:hotpink;">{{ day }}</td> 41 41 {% else %} 42 42 <td>{{ day }}</td> 43 43 {% endif %} 44 44 {% endfor %} 45 45 </tr> 46 46 {% endfor %} 47 47 {% endwith %} 48 48 </table> 49 49 </div> 50 50 {% endfor %} 51 51 52 52</div> 53 53 54 54</body> 55 55<footer class="text-center "><strong><a href="https://www.jianshu.com/u/d23fd5012bed">Flask Calendar By:清风Python</a></strong></footer> 56 56</html>
JInjia2模板中,通过对with 和set的局部变量定义,判断月份与日期,最终达到高亮当月和当天的效果:
当天高亮效果
再来看看完整的效果展示:
完整代码:
代码目录
1 1# -*- coding: utf-8 -*- 2 2# @Author : 王翔 3 3# @JianShu : 清风Python 4 4# @Date : 2019/6/4 06:01 5 5# @Software : PyCharm 6 6# @version :Python 3.6.8 7 7# @File : index.py 8 8 9 9from flask import Flask, render_template, request, session, redirect, url_for 10 10import calendar 11 11from datetime import datetime 12 12 13 13calendar.setfirstweekday(firstweekday=6) 14 14app = Flask(__name__) 15 15 16 16week = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] 17 17 18 18 19 19def calc_calender(date): 20 20 year = date.year 21 21 yearInfo = dict() 22 22 for month in range(1, 13): 23 23 days = calendar.monthcalendar(year, month) 24 24 if len(days) != 6: 25 25 days.append([0 for _ in range(7)]) 26 26 month_addr = calendar.month_abbr[month] 27 27 yearInfo[month_addr] = days 28 28 return yearInfo 29 29 30 30 31 31@app.route('/', methods=["GET", "POST"]) 32 32def index(): 33 33 if request.method == "GET": 34 34 date = datetime.today() 35 35 this_month = calendar.month_abbr[date.month] 36 36 return render_template('index.html', this_month=this_month, date=date, content=calc_calender(date)) 37 37 38 38 39 39if __name__ == '__main__': 40 40 app.run(debug=True)
作者:华为云特约供稿开发者 清风Python