|
4 | 4 |
|
5 | 5 | from typing import List |
6 | 6 |
|
7 | | -from fastapi import APIRouter, Depends, HTTPException |
8 | | -from fastapi.staticfiles import StaticFiles |
| 7 | +import requests |
| 8 | +from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, Request |
9 | 9 | from fastapi.templating import Jinja2Templates |
| 10 | +from pydantic import HttpUrl |
10 | 11 | from sqlalchemy.orm import Session |
11 | 12 |
|
12 | 13 | from coronavirus import crud, schemas |
13 | 14 | from coronavirus.database import engine, Base, SessionLocal |
| 15 | +from coronavirus.models import City, Data |
14 | 16 |
|
15 | 17 | application = APIRouter() |
16 | 18 |
|
17 | | -# mount表示将某个目录下一个完全独立的应用挂载过来,这个不会在API交互文档中显示 |
18 | | -application.mount('/static', StaticFiles(directory='./coronavirus/static'), name='static') |
19 | 19 | templates = Jinja2Templates(directory='./coronavirus/templates') |
20 | 20 |
|
21 | 21 | Base.metadata.create_all(bind=engine) |
@@ -58,7 +58,57 @@ def create_data_for_city(city: str, data: schemas.CreateData, db: Session = Depe |
58 | 58 | return data |
59 | 59 |
|
60 | 60 |
|
61 | | -@application.get("/get_data", response_model=List[schemas.ReadData]) |
62 | | -def get_data(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): |
63 | | - data = crud.get_data(db, skip=skip, limit=limit) |
| 61 | +@application.get("/get_data") |
| 62 | +def get_data(city: str = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): |
| 63 | + data = crud.get_data(db, city=city, skip=skip, limit=limit) |
64 | 64 | return data |
| 65 | + |
| 66 | + |
| 67 | +def bg_task(url: HttpUrl, db: Session): |
| 68 | + """这里注意一个坑,不要在后台任务的参数中db: Session = Depends(get_db)这样导入依赖""" |
| 69 | + |
| 70 | + city_data = requests.get(url=f"{url}?source=jhu&country_code=CN&timelines=false") |
| 71 | + |
| 72 | + if 200 == city_data.status_code: |
| 73 | + db.query(City).delete() # 同步数据前先清空原有的数据 |
| 74 | + for location in city_data.json()["locations"]: |
| 75 | + city = { |
| 76 | + "province": location["province"], |
| 77 | + "country": location["country"], |
| 78 | + "country_code": "CN", |
| 79 | + "country_population": location["country_population"] |
| 80 | + } |
| 81 | + crud.create_city(db=db, city=schemas.CreateCity(**city)) |
| 82 | + |
| 83 | + coronavirus_data = requests.get(url=f"{url}?source=jhu&country_code=CN&timelines=true") |
| 84 | + |
| 85 | + if 200 == coronavirus_data.status_code: |
| 86 | + db.query(Data).delete() |
| 87 | + for city in coronavirus_data.json()["locations"]: |
| 88 | + db_city = crud.get_city_by_name(db=db, name=city["province"]) |
| 89 | + for date, confirmed in city["timelines"]["confirmed"]["timeline"].items(): |
| 90 | + data = { |
| 91 | + "date": date.split("T")[0], # 把'2020-12-31T00:00:00Z' 变成 ‘2020-12-31’ |
| 92 | + "confirmed": confirmed, |
| 93 | + "deaths": city["timelines"]["deaths"]["timeline"][date], |
| 94 | + "recovered": 0 # 每个城市每天有多少人痊愈,这种数据没有 |
| 95 | + } |
| 96 | + # 这个city_id是city表中的主键ID,不是coronavirus_data数据里的ID |
| 97 | + crud.create_city_data(db=db, data=schemas.CreateData(**data), city_id=db_city.id) |
| 98 | + |
| 99 | + |
| 100 | +@application.get("/sync_coronavirus_data/jhu") |
| 101 | +def sync_coronavirus_data(background_tasks: BackgroundTasks, db: Session = Depends(get_db)): |
| 102 | + """从Johns Hopkins University同步COVID-19数据""" |
| 103 | + background_tasks.add_task(bg_task, "https://coronavirus-tracker-api.herokuapp.com/v2/locations", db) |
| 104 | + return {"message": "正在后台同步数据..."} |
| 105 | + |
| 106 | + |
| 107 | +@application.get("/") |
| 108 | +def coronavirus(request: Request, city: str = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): |
| 109 | + data = crud.get_data(db, city=city, skip=skip, limit=limit) |
| 110 | + return templates.TemplateResponse("home.html", { |
| 111 | + "request": request, |
| 112 | + "data": data, |
| 113 | + "sync_data_url": "/coronavirus/sync_coronavirus_data/jhu" |
| 114 | + }) |
0 commit comments