feat: 添加网站地图生成功能并优化公共文件访问
- 新增生成sitemap.xml的功能,包含静态和动态路由 - 优化公共文件访问接口,支持直接返回sitemap.xml
This commit is contained in:
parent
345c571dda
commit
6e49fadbab
67
app.py
67
app.py
@ -1,24 +1,18 @@
|
||||
from fastapi import FastAPI, Request, HTTPException
|
||||
from fastapi.responses import HTMLResponse, FileResponse
|
||||
from fastapi.responses import HTMLResponse, FileResponse, Response
|
||||
import markdown
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
import json, yaml
|
||||
import os
|
||||
import uvicorn
|
||||
from datetime import datetime
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
app = FastAPI()
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
|
||||
# Mount all files from public directory to root
|
||||
@app.get("/{filename}")
|
||||
async def get_public_file(filename: str):
|
||||
public_path = os.path.join("public", filename)
|
||||
if os.path.isfile(public_path):
|
||||
return FileResponse(public_path)
|
||||
raise HTTPException(status_code=404, detail="File not found")
|
||||
|
||||
# 加载所有问卷数据
|
||||
def load_all_scales():
|
||||
scales = {}
|
||||
@ -112,6 +106,61 @@ async def result(request: Request, scale_id: str):
|
||||
})
|
||||
raise HTTPException(status_code=404, detail="问卷未找到")
|
||||
|
||||
def generate_sitemap():
|
||||
# Create the root element
|
||||
urlset = ET.Element("urlset", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
|
||||
|
||||
latest_mtime = max(
|
||||
os.path.getmtime(os.path.join(root, f))
|
||||
for root, _, files in os.walk('scales')
|
||||
for f in files if f.endswith(('.yaml', '.yml'))
|
||||
)
|
||||
|
||||
# Add static routes
|
||||
static_routes = ["/"] # Add your static routes here
|
||||
for route in static_routes:
|
||||
url = ET.SubElement(urlset, "url")
|
||||
ET.SubElement(url, "loc").text = f"https://psychoscales.org{route}"
|
||||
ET.SubElement(url, "lastmod").text = datetime.fromtimestamp(latest_mtime).strftime("%Y-%m-%d")
|
||||
ET.SubElement(url, "changefreq").text = "monthly"
|
||||
ET.SubElement(url, "priority").text = "0.8"
|
||||
|
||||
# Add dynamic tag routes
|
||||
tags, scales = load_all_scales()
|
||||
for tag in tags:
|
||||
url = ET.SubElement(urlset, "url")
|
||||
ET.SubElement(url, "loc").text = f"https://psychoscales.org/tag/{tag}"
|
||||
ET.SubElement(url, "lastmod").text = datetime.fromtimestamp(latest_mtime).strftime("%Y-%m-%d")
|
||||
ET.SubElement(url, "changefreq").text = "weekly"
|
||||
ET.SubElement(url, "priority").text = "0.6"
|
||||
|
||||
# Add dynamic scale routes
|
||||
for scale_id in scales.keys():
|
||||
url = ET.SubElement(urlset, "url")
|
||||
ET.SubElement(url, "loc").text = f"https://psychoscales.org/scales/{scale_id}"
|
||||
# For individual scale pages, use the actual file modification time
|
||||
scale_file = os.path.join('scales', f"{scale_id}.yaml")
|
||||
if os.path.exists(scale_file):
|
||||
mtime = os.path.getmtime(scale_file)
|
||||
ET.SubElement(url, "lastmod").text = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d")
|
||||
ET.SubElement(url, "changefreq").text = "monthly"
|
||||
ET.SubElement(url, "priority").text = "0.6"
|
||||
|
||||
# Convert to string
|
||||
return ET.tostring(urlset, encoding='unicode', method='xml')
|
||||
|
||||
# Mount all files from public directory to root
|
||||
@app.get("/{filename}")
|
||||
async def get_public_file(filename: str):
|
||||
public_path = os.path.join("public", filename)
|
||||
if filename == "sitemap.xml":
|
||||
return Response(
|
||||
content=generate_sitemap(),
|
||||
media_type="application/xml"
|
||||
)
|
||||
if os.path.isfile(public_path):
|
||||
return FileResponse(public_path)
|
||||
raise HTTPException(status_code=404, detail="File not found")
|
||||
|
||||
if __name__ == '__main__':
|
||||
uvicorn.run(app,host='0.0.0.0',port=8000)
|
Loading…
x
Reference in New Issue
Block a user