手把手教你使用Python打造一款摸魚倒計界面
回復(fù)“書籍”即可獲贈Python從入門到進階共10本電子書
大家好,我是吳老板。
前言
前段時間在微博看到一段摸魚人的倒計時模板,感覺還挺有趣的。

于是我用了一小時的時間寫了個頁面出來 摸魚辦地址 (當(dāng)然是摸魚的時間啦)。
模板是這樣的:
摸魚辦公室 ??
你好,摸魚人,工作再累,一定不要忘記摸魚哦 ! 有事沒事起身去茶水間去廊道去天臺走走,別老在工位上坐著。多喝點水,錢是老板的,但命是自己的 !
?? 距離 周末 放假還有 2 天
?? 距離 元旦 放假還有 3 天
?? 距離 過年 放假還有 34 天
?? 距離 清明節(jié) 放假還有 97 天
?? 距離 勞動節(jié) 放假還有 123 天
?? 距離 端午節(jié) 放假還有 156 天
?? 距離 中秋節(jié) 放假還有 255 天
?? 距離 國慶節(jié) 放假還有 276 天
由于前端是單頁面服務(wù),直接擼一個原始的 html網(wǎng)頁就行。FastAPI對于異步請求是一把好手、更輕、性能更佳。掛上一層 Nginx讓它看起來像那么回事兒。
實現(xiàn)過程
首先要知道、除了靜態(tài)文字之外的比如當(dāng)前日期、距離節(jié)日放假的天數(shù)等都是動態(tài)返回的,我需要使用 Jinja2 模板進行動態(tài)綁定。 我應(yīng)該把重點放在時間的處理上。 而且在這個模板中,有陽歷的節(jié)日,也是陰歷的節(jié)日,我需要轉(zhuǎn)換。
初始化一個 FastAPI 對象并聲明靜態(tài)頁面的模板目錄 (Jinja2Templates)
#?-*-?coding:?utf-8?-*-
import?datetime
from?fastapi?import?FastAPI,?Request
from?fastapi.responses?import?HTMLResponse
from?fastapi.templating?import?Jinja2Templates
from?zhdate?import?ZhDate?as?lunar_date
app?=?FastAPI(
????debug=False,
????title="My?API",
????docs_url="/docs",
????openapi_url=f"/openapi.json"
)
templates?=?Jinja2Templates(directory="templates")
可以看到的是我用到了 zhdate 這個庫、主要用于陰歷和陽歷之間的相互轉(zhuǎn)換。用法如下
today?=?datetime.date.today()
print(today.year,?today.month,?today.day)
print("大年時間:?",?lunar_date(today.year+1,?1,?1).to_datetime().date())
print("端午時間:?",?lunar_date(today.year,?5,?5).to_datetime().date())
print("中秋時間:?",?lunar_date(today.year,?8,?15).to_datetime().date())
print("元旦時間:?",?f"{today.year+1}-01-01")
print("清明時間:?",?f"{today.year}-04-05")
print("勞動時間:?",?f"{today.year}-05-01")
print("國慶時間:?",?f"{today.year}-10-01")
我們可以梳理一下:
計算距離 大年、元旦的天數(shù)時,要在年份上+1計算距離 其他節(jié)日的天數(shù)時,要判斷天數(shù)差是否小于0,如果是,則年份需要+1,因為已經(jīng)過去的節(jié)日對此沒有意義
distance_big_year?=?(lunar_date(today.year?+?1,?1,?1).to_datetime().date()?-?today).days
distance_5_5?=?(lunar_date(today.year,?5,?5).to_datetime().date()?-?today).days
distance_5_5?=?distance_5_5?if?distance_5_5?>?0?else?(
????????lunar_date(today.year?+?1,?5,?5).to_datetime().date()?-?today).days
distance_8_15?=?(lunar_date(today.year,?8,?15).to_datetime().date()?-?today).days
distance_8_15?=?distance_8_15?if?distance_8_15?>?0?else?(
????????lunar_date(today.year?+?1,?8,?15).to_datetime().date()?-?today).days
distance_year?=?(datetime.datetime.strptime(f"{today.year?+?1}-01-01",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?(datetime.datetime.strptime(f"{today.year}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?distance_4_5?if?distance_4_5?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?(datetime.datetime.strptime(f"{today.year}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?distance_5_1?if?distance_5_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?(datetime.datetime.strptime(f"{today.year}-10-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?distance_10_1?if?distance_10_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-10-01",?"%Y-%m-%d").date()?-?today).days
怎么樣? 我的命名足夠瘋狂吧。
接下來需要計算一下距離周末的天數(shù)。
def?get_week_day(date):
????week_day_dict?=?{
????????0:?'星期一',
????????1:?'星期二',
????????2:?'星期三',
????????3:?'星期四',
????????4:?'星期五',
????????5:?'星期六',
????????6:?'星期天',
????}
????day?=?date.weekday()
????return?week_day_dict[day]
week_day_?=?get_week_day(today)
print(f"今天是:?{week_day_}")?#?先獲取今天是星期幾
按照每周 5 個工作日計算,今天距離周末的天數(shù)就是
5?-?today.weekday()?#?today.weekday()?今天距離周末
現(xiàn)在將所有的數(shù)據(jù)組裝起來
time_?=?[
????{"v_":?distance_year,?"title":?"元旦"},??#?距離元旦
????{"v_":?distance_big_year,?"title":?"過年"},??#?距離過年
????{"v_":?distance_4_5,?"title":?"清明節(jié)"},??#?距離清明
????{"v_":?distance_5_1,?"title":?"勞動節(jié)"},??#?距離勞動
????{"v_":?distance_5_5,?"title":?"端午節(jié)"},??#?距離端午
????{"v_":?distance_8_15,?"title":?"中秋節(jié)"},??#?距離中秋
????{"v_":?distance_10_1,?"title":?"國慶節(jié)"},??#?距離國慶
]
至于為什么是 List 而不是 Dict,那是我需要做一個根據(jù)距離天數(shù)的排序,讓最先放假的節(jié)日放于最前面,
這樣看起來會舒服得多。
time_?=?sorted(time_,?key=lambda?x:?x['v_'],?reverse=False)
接下來要寫一個 路由,將數(shù)據(jù)傳入到 html 頁面中去。
@app.get("/",?response_class=HTMLResponse)
async?def?readme(request:?Request):
????return?templates.TemplateResponse("readme.html",
??????????????????????????????????????{"request":?request,?"time_":?time_,?"now_":?now_,?"week_day_":?week_day_})
來看一下完整的代碼 (main.py):
#?-*-?coding:?utf-8?-*-
import?datetime
from?fastapi?import?FastAPI,?Request
from?fastapi.responses?import?HTMLResponse
from?fastapi.templating?import?Jinja2Templates
from?zhdate?import?ZhDate?as?lunar_date
app?=?FastAPI(
????debug=False,
????title="My?API",
????docs_url=f"/docs",
????openapi_url=f"/openapi.json"
)
templates?=?Jinja2Templates(directory="templates")
today?=?datetime.date.today()
#?print(today.year,?today.month,?today.day)
#?print("大年時間:?",?lunar_date(today.year+1,?1,?1).to_datetime().date())
#?print("端午時間:?",?lunar_date(today.year,?5,?5).to_datetime().date())
#?print("中秋時間:?",?lunar_date(today.year,?8,?15).to_datetime().date())
#?print("元旦時間:?",?f"{today.year+1}-01-01")
#?print("清明時間:?",?f"{today.year+1}-04-05")
#?print("勞動時間:?",?f"{today.year+1}-05-01")
#?print("國慶時間:?",?f"{today.year+1}-10-01")
distance_big_year?=?(lunar_date(today.year?+?1,?1,?1).to_datetime().date()?-?today).days
distance_5_5?=?(lunar_date(today.year,?5,?5).to_datetime().date()?-?today).days
distance_5_5?=?distance_5_5?if?distance_5_5?>?0?else?(
????????lunar_date(today.year?+?1,?5,?5).to_datetime().date()?-?today).days
distance_8_15?=?(lunar_date(today.year,?8,?15).to_datetime().date()?-?today).days
distance_8_15?=?distance_8_15?if?distance_8_15?>?0?else?(
????????lunar_date(today.year?+?1,?8,?15).to_datetime().date()?-?today).days
distance_year?=?(datetime.datetime.strptime(f"{today.year?+?1}-01-01",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?(datetime.datetime.strptime(f"{today.year}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?distance_4_5?if?distance_4_5?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?(datetime.datetime.strptime(f"{today.year}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?distance_5_1?if?distance_5_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?(datetime.datetime.strptime(f"{today.year}-10-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?distance_10_1?if?distance_10_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-10-01",?"%Y-%m-%d").date()?-?today).days
def?get_week_day(date):
????week_day_dict?=?{
????????0:?'星期一',
????????1:?'星期二',
????????2:?'星期三',
????????3:?'星期四',
????????4:?'星期五',
????????5:?'星期六',
????????6:?'星期天',
????}
????day?=?date.weekday()
????return?week_day_dict[day]
#?print("距離大年:?",?distance_big_year)
#?print("距離端午:?",?distance_5_5)
#?print("距離中秋:?",?distance_8_15)
#?print("距離元旦:?",?distance_year)
#?print("距離清明:?",?distance_4_5)
#?print("距離勞動:?",?distance_5_1)
#?print("距離國慶:?",?distance_10_1)
#?print("距離周末:?",?5?-?today.weekday())
now_?=?f"{today.year}年{today.month}月{today.day}日"
week_day_?=?get_week_day(today)
time_?=?[
????{"v_":?5?-?1?-?today.weekday(),?"title":?"周末"},??#?距離周末
????{"v_":?distance_year,?"title":?"元旦"},??#?距離元旦
????{"v_":?distance_big_year,?"title":?"過年"},??#?距離過年
????{"v_":?distance_4_5,?"title":?"清明節(jié)"},??#?距離清明
????{"v_":?distance_5_1,?"title":?"勞動節(jié)"},??#?距離勞動
????{"v_":?distance_5_5,?"title":?"端午節(jié)"},??#?距離端午
????{"v_":?distance_8_15,?"title":?"中秋節(jié)"},??#?距離中秋
????{"v_":?distance_10_1,?"title":?"國慶節(jié)"},??#?距離國慶
]
time_?=?sorted(time_,?key=lambda?x:?x['v_'],?reverse=False)
@app.get("/",?response_class=HTMLResponse)
async?def?readme(request:?Request):
????return?templates.TemplateResponse("readme.html",
??????????????????????????????????????{"request":?request,?"time_":?time_,?"now_":?now_,?"week_day_":?week_day_})
if?__name__?==?'__main__':
????import?uvicorn
????uvicorn.run(app='main:app',?host="0.0.0.0",?port=8080,?reload=True)
最后就到了 html 頁面部分了,來看一下主要的傳值。
<center>
????【摸魚辦公室】今天是?{{?now_?}}?{{?week_day_?}}
????<br><br>
????{%?for?v_?in?time_?%}
????????<p>???距離?{{?v_.title?}}?放假還有?{{?v_.v_?}}?天p>
????{%?else?%}
????????<p>沒有任何值p>
????{%?endfor?%}
center>
這樣整個的路由構(gòu)造和頁面編寫就算是完成了。
最后通過 Nginx 部署到我的站點上。
摸魚辦預(yù)覽地址

代碼已經(jīng)上傳至 摸魚辦:
https://github.com/PY-GZKY/moyu你可能會有更多的想法、可以在評論區(qū)討論、一切為了摸魚。

小伙伴們,快快用實踐一下吧!如果在學(xué)習(xí)過程中,有遇到任何問題,歡迎加我好友,我拉你進Python學(xué)習(xí)交流群共同探討學(xué)習(xí)。
-------------------?End?-------------------
往期精彩文章推薦:
Py自動化辦公—Word文檔替換、Excel表格讀取、Pdf文件生成和Email自動郵件發(fā)送實戰(zhàn)案例
手把手教你用Python批量創(chuàng)建1-12月份的sheet表,每個表的第一行都有固定3個列標(biāo)題:A,B,C

歡迎大家點贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持
想加入Python學(xué)習(xí)群請在后臺回復(fù)【入群】
萬水千山總是情,點個【在看】行不行
/今日留言主題/
隨便說一兩句吧~~
