preface

Some time ago, I saw a countdown template of people who touch fish on Weibo, which was quite interesting.


So I spent an hour writing a page to create the address of the fish office (the time of the fish, of course).

The template looks like this:

Fishing office 🐟

Today is 2021-11-30 Tuesday \

Hello, fish person, work no matter how tired, must not forget to fish oh! Something is nothing to get up to go to the tea room to walk the corridor to the roof, do not sit on the station. Drink more water, money is the boss, but life is their own!

🐟 2 days before the weekend holiday

🐟 There are 3 days left before the New Year holiday

🐟 There are 34 days left before the Chinese New Year holiday

🐟 There are 97 days left before the Tomb-sweeping Day holiday

🐟 there are 123 days until the Labor Day holiday

🐟 There are 156 days left before the Dragon Boat Festival holiday

🐟 there are 255 days left until the Chuseok holiday

🐟 there are 276 days left before the National Day holiday


  • Since the front end is a single page service, it is directly stroked to an originalhtmlA web page will do.
  • FastAPIGood for asynchronous requests, lighter and better performance.
  • Hang a layerNginxMake it look like it’s the real deal.

The implementation process

  • The first thing to know is that anything other than static text such as the current date, the number of days since the holiday, etc. is returned dynamically and I need to use the Jinja2 template for dynamic binding.
  • I should have focused on time management.
  • And in this template, there are holidays in the solar calendar, also in the lunar calendar, and I need to switch.

Initialize a FastAPI object and declare the static page’s template directory (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")
Copy the code

As you can see, I used the zhdate library, mainly for converting between lunar and solar calendars. Use the following

Date = 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 (). The date ()) print (" New Year's day time:, "f" {today. The year + 1} - 01-01 ") print (" qingming festival time: , "f" {today. Year} - 04 - '05 ") print (" labor time:, "f" {today. Year} - 05-01 ") print (", "National Day time, f" {today. Year} - 10-01 ")Copy the code

We can sort it out:

  • Calculation of distanceNew Year, New Year's DayThe number of days is in the year+ 1
  • Calculation of distanceThe other dayIs used to determine whether the difference is smaller than0If yes, the year is required+ 1Because the festivals that have passed have no meaning
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).daysCopy the code

How’s that? I think my naming is crazy enough. Then you need to calculate the number of days until the weekend.

Def get_week_day (date) : week_day_dict = {0: 'on Monday, 1:' on Tuesday, 2: 'on Wednesday, 3:' on Thursday, 4: 'Friday, 5:' Saturday, 6: } day = date.weekday() return week_day_dict[day] week_day_ = get_week_day(today) print(f" {week_day_}") #Copy the code

Based on the 5 working days per week, today is the number of days to the weekend

5 - today.weekday() # today.weekday(Copy the code

Now assemble all the data

Time_ = [{" v_ ": distance_year," title ":" New Year's day "}, # from New Year's day {" v_ ": distance_big_year," title ":" New Year "}, New Year's day {# distance "v_" : Distance_4_5, "title" : "qingming festival"}, # distance tomb-sweeping {" v_ ": distance_5_1," title ":" labor day "}, {# from labor "v_" : distance_5_5, "title" : Dragon Boat Festival "Dragon Boat Festival"}, # distance {" v_ ": distance_8_15," title ":" Mid-Autumn festival "}, # distance Mid-Autumn {" v_ ": distance_10_1," title ":" National Day "}, National Day] # distanceCopy the code

As for why it was a List instead of Dict, I needed to do a sort by distance, and put the first holiday first so it would look much more comfortable.

time_ = sorted(time_, key=lambda x: x['v_'], reverse=False)
Copy the code

The next step is to write a route that passes the data to the HTML page.

@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_})
Copy the code

Take a look at the complete code (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(" today.year, today.month, today.day" ", 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 (). The date ()) # print (" New Year's day time:, "f" {today. The year + 1} - 01-01 ") # print (" qingming festival time: "F" {today. The year + 1} - 04 - '05) # print "(" labor time:," f "{today. The year + 1} - 05-01") # print (" National Day time: ", 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: 'Monday', 1: 'on Tuesday, 2:' on Wednesday, 3: 'on Thursday, 4:' Friday, 5: 'Saturday, 6: } day = date.weekday() return week_day_dict[day] # print(" distance_big_year: ", distance_big_year) # print(" distance_big_year: ") ", distance_year) # print(" distance_year: ", distance_year) # print(" distance_year: ") # print(" distance_year: ") # print(" ", distance_4_5) # print (" labor: distance, "distance_5_1) # print (" from the National Day:" distance_10_1) # print (" distance weekend: ", 5 - today.weekday()) now_ = f"{today.year} {today.month} month {today.day} day "week_day_ = get_week_day(today) time_ = [{"v_": 5-1 - today. Weekday (), "title" : "weekend"}, # distance weekend {" v_ ": distance_year," title ":" New Year's day "}, {# from New Year's day "v_" : Distance_big_year, "title" : "New Year"}, # distance for {" v_ ": distance_4_5," title ":" qingming festival "}, {# distance qingming festival "v_" : distance_5_1, "title" : "Labor day"}, # from labor {" v_ ": distance_5_5," title ":" the Dragon Boat Festival "}, # distance dragon boat {" v_ ": distance_8_15," title ":" Mid-Autumn festival "}, # distance Mid-Autumn {" v_ ": Distance_10_1, "title": "National Day "}, # remote day] 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)Copy the code

Finally, we come to the HTML page section, where we take a look at the main pass values.

< center > today is fishing in the office 】 【 {{now_}} {{week_day_}} < br > < br > {% for v_ in time_ %} < p > 🐟 distance {{v_. Title}} and {{v_. V_}} the holiday Day < / p >} else {% % < p > no value < / p > {% endfor %} < / center >Copy the code

This completes the entire route construction and page authoring.