feat: 新增技能扩展N7一章相关示例源码
This commit is contained in:
56
code/newsletter/N7/cli.py
Normal file
56
code/newsletter/N7/cli.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import argparse
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
import jinja2
|
||||||
|
|
||||||
|
ROOT = pathlib.Path(__file__).parent
|
||||||
|
TEMPLATE = ROOT / "templates/project"
|
||||||
|
|
||||||
|
env = jinja2.Environment(
|
||||||
|
trim_blocks=True,
|
||||||
|
loader=jinja2.FileSystemLoader(TEMPLATE),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_cli():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparser = parser.add_subparsers()
|
||||||
|
|
||||||
|
startapp = subparser.add_parser("startapp")
|
||||||
|
startapp.add_argument(
|
||||||
|
"name",
|
||||||
|
type=str,
|
||||||
|
help="the app name",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def build_layout(name: str):
|
||||||
|
app_dir = ROOT.joinpath(f"{name}")
|
||||||
|
if app_dir.exists():
|
||||||
|
print(f"{name} directory has exists!")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
app_dir.mkdir()
|
||||||
|
|
||||||
|
for base in TEMPLATE.iterdir():
|
||||||
|
basename = base.stem
|
||||||
|
fpath = app_dir.joinpath(f"{basename}")
|
||||||
|
if basename == "__init__.py":
|
||||||
|
fpath.write_text("")
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(fpath, mode="w+", encoding="utf-8") as f:
|
||||||
|
content = env.get_template(base.name).render(app_name=name)
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = setup_cli()
|
||||||
|
args = parser.parse_args()
|
||||||
|
print(args)
|
||||||
|
build_layout(name=args.name)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
397
code/newsletter/N7/quickstart.ipynb
Normal file
397
code/newsletter/N7/quickstart.ipynb
Normal file
@@ -0,0 +1,397 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import jinja2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# variables"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"your variable value: 100gle\n",
|
||||||
|
"\n",
|
||||||
|
"inner set variable value: author\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"tpl = \"\"\"\\\n",
|
||||||
|
"your variable value: {{ name }}\n",
|
||||||
|
"{% set badge=\"author\" %}\n",
|
||||||
|
"inner set variable value: {{ badge }}\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"template = jinja2.Template(tpl)\n",
|
||||||
|
"s = template.render(name=\"100gle\")\n",
|
||||||
|
"print(s)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 50,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'Hello, world\\n'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 50,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"tpl = \"\"\"\\\n",
|
||||||
|
"Hello, world\n",
|
||||||
|
"{# this line wouldn't be rendered. #}\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"template = jinja2.Template(tpl)\n",
|
||||||
|
"template.render()\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# for loop"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 10,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" * Reading\n",
|
||||||
|
" * Home Work\n",
|
||||||
|
" * Exercise\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"tpl = \"\"\"\\\n",
|
||||||
|
"{# use for-loop in jinja2 #}\n",
|
||||||
|
"{% for todo in todolist %}\n",
|
||||||
|
" * {{ todo }}\n",
|
||||||
|
"{% endfor %}\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"todolist = [\"Reading\", \"Home Work\", \"Exercise\"]\n",
|
||||||
|
"template = jinja2.Template(tpl, trim_blocks=True)\n",
|
||||||
|
"s = template.render(todolist=todolist)\n",
|
||||||
|
"print(s)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" name: Reading\n",
|
||||||
|
" priority: 2\n",
|
||||||
|
" name: Home Work\n",
|
||||||
|
" priority: 0\n",
|
||||||
|
" name: Exercise\n",
|
||||||
|
" priority: 1\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"tpl = \"\"\"\\\n",
|
||||||
|
"{# use for-loop in jinja2 #}\n",
|
||||||
|
"{% for todo in todolist %}\n",
|
||||||
|
" {% for key, value in todo.items() %}\n",
|
||||||
|
" {{ key }}: {{ value }}\n",
|
||||||
|
" {% endfor %}\n",
|
||||||
|
"{% endfor %}\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"todolist = [\n",
|
||||||
|
" dict(name=\"Reading\", priority=2),\n",
|
||||||
|
" dict(name=\"Home Work\", priority=0),\n",
|
||||||
|
" dict(name=\"Exercise\", priority=1),\n",
|
||||||
|
"]\n",
|
||||||
|
"template = jinja2.Template(tpl, trim_blocks=True, lstrip_blocks=True)\n",
|
||||||
|
"s = template.render(todolist=todolist)\n",
|
||||||
|
"print(s)\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# if-else"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 52,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" Reading**\n",
|
||||||
|
" Home Work\n",
|
||||||
|
" Exercise*\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"tpl = \"\"\"\\\n",
|
||||||
|
"{% for todo in todolist %}\n",
|
||||||
|
" {% if todo.priority == 2 %}\n",
|
||||||
|
" {{ todo.name }}**\n",
|
||||||
|
" {% elif todo.priority == 1 %}\n",
|
||||||
|
" {{ todo.name }}*\n",
|
||||||
|
" {% else %}\n",
|
||||||
|
" {{ todo.name }}\n",
|
||||||
|
" {% endif %}\n",
|
||||||
|
"{% endfor %}\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"todolist = [\n",
|
||||||
|
" dict(name=\"Reading\", priority=2),\n",
|
||||||
|
" dict(name=\"Home Work\", priority=0),\n",
|
||||||
|
" dict(name=\"Exercise\", priority=1),\n",
|
||||||
|
"]\n",
|
||||||
|
"\n",
|
||||||
|
"template = jinja2.Template(tpl, lstrip_blocks=True, trim_blocks=True)\n",
|
||||||
|
"s = template.render(todolist=todolist)\n",
|
||||||
|
"print(s)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# macros"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 17,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"\n",
|
||||||
|
" Reading**\n",
|
||||||
|
" Home Work\n",
|
||||||
|
" Exercise*\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"tpl = \"\"\"\\\n",
|
||||||
|
"{% macro show_todo(name, priority) -%}\n",
|
||||||
|
" {% set marker=\"\" %}\n",
|
||||||
|
" {% if priority == 2 %}\n",
|
||||||
|
" {% set marker = \"**\" %}\n",
|
||||||
|
" {% elif priority == 1 %}\n",
|
||||||
|
" {% set marker = \"*\" %}\n",
|
||||||
|
" {% endif %}\n",
|
||||||
|
" {{ name }}{{ marker }}\n",
|
||||||
|
"{%- endmacro %}\n",
|
||||||
|
"\n",
|
||||||
|
"{% for todo in todolist %}\n",
|
||||||
|
" {{ show_todo(todo.name, todo.priority) }}\n",
|
||||||
|
"{% endfor %}\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"todolist = [\n",
|
||||||
|
" dict(name=\"Reading\", priority=2),\n",
|
||||||
|
" dict(name=\"Home Work\", priority=0),\n",
|
||||||
|
" dict(name=\"Exercise\", priority=1),\n",
|
||||||
|
"]\n",
|
||||||
|
"\n",
|
||||||
|
"template = jinja2.Template(tpl, trim_blocks=True, lstrip_blocks=True)\n",
|
||||||
|
"s = template.render(todolist=todolist)\n",
|
||||||
|
"print(s)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# filter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 15,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" - before: $10.99, after: 10.99\n",
|
||||||
|
" - before: €0.99, after: 0.99\n",
|
||||||
|
" - before: ¥100, after: 100\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"def remove_currerncy(val: str):\n",
|
||||||
|
" currencies = set(\"$€¥\")\n",
|
||||||
|
" if val[0] in currencies:\n",
|
||||||
|
" return val[1:]\n",
|
||||||
|
" return val\n",
|
||||||
|
"\n",
|
||||||
|
"tpl = \"\"\"\\\n",
|
||||||
|
"{% for value in money %}\n",
|
||||||
|
" - before: {{ value }}, after: {{ value|remove_currency}}\n",
|
||||||
|
"{% endfor %}\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"money = [\"$10.99\", \"€0.99\", \"¥100\"]\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"env = jinja2.Environment(trim_blocks=True)\n",
|
||||||
|
"env.filters[\"remove_currency\"] = remove_currerncy\n",
|
||||||
|
"\n",
|
||||||
|
"template = env.from_string(tpl)\n",
|
||||||
|
"s = template.render(money=money)\n",
|
||||||
|
"print(s)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# inheritance"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 9,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"# bug: TemplateNotFound error should be fixed.\n",
|
||||||
|
"\n",
|
||||||
|
"Your environment:\n",
|
||||||
|
"\n",
|
||||||
|
" - python version: 3.9\n",
|
||||||
|
" - jinja2: 3.2.x\n",
|
||||||
|
" \n",
|
||||||
|
"---\n",
|
||||||
|
"\n",
|
||||||
|
"Bug detail:\n",
|
||||||
|
"\n",
|
||||||
|
"More description here:\n",
|
||||||
|
"\n",
|
||||||
|
" ```python\n",
|
||||||
|
" ...\n",
|
||||||
|
" ```\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"env = jinja2.Environment(\n",
|
||||||
|
" trim_blocks=True,\n",
|
||||||
|
" loader=jinja2.FileSystemLoader(\"./templates/inheritance/\"),\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"template = env.get_template(\"bug_report.md\")\n",
|
||||||
|
"s = template.render(\n",
|
||||||
|
" title=\"bug: TemplateNotFound error should be fixed.\",\n",
|
||||||
|
" setup=[\n",
|
||||||
|
" dict(name=\"python version\", detail=3.9),\n",
|
||||||
|
" dict(name=\"jinja2\", detail=\"3.2.x\"),\n",
|
||||||
|
" ],\n",
|
||||||
|
" description=\"\"\"\\\n",
|
||||||
|
"More description here:\n",
|
||||||
|
"\n",
|
||||||
|
" ```python\n",
|
||||||
|
" ...\n",
|
||||||
|
" ```\n",
|
||||||
|
" \"\"\".strip()\n",
|
||||||
|
")\n",
|
||||||
|
"print(s)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3.9.0 ('pandas-startup')",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.9.0"
|
||||||
|
},
|
||||||
|
"orig_nbformat": 4,
|
||||||
|
"vscode": {
|
||||||
|
"interpreter": {
|
||||||
|
"hash": "13977d4cc82dee5f9d9535ceb495bd0ab12a43c33c664e5f0d53c24cf634b67f"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 2
|
||||||
|
}
|
||||||
11
code/newsletter/N7/templates/inheritance/base.md
Normal file
11
code/newsletter/N7/templates/inheritance/base.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# {% block title %}{% endblock %}
|
||||||
|
|
||||||
|
Your environment:
|
||||||
|
|
||||||
|
{% block environment %}{% endblock %}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Bug detail:
|
||||||
|
|
||||||
|
{% block description %}{% endblock %}
|
||||||
15
code/newsletter/N7/templates/inheritance/bug_report.md
Normal file
15
code/newsletter/N7/templates/inheritance/bug_report.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% extends "base.md" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{{ title }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block environment %}
|
||||||
|
{% for item in setup %}
|
||||||
|
- {{ item.name }}: {{ item.detail }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block description %}
|
||||||
|
{{ description }}
|
||||||
|
{% endblock %}
|
||||||
18
code/newsletter/N7/templates/project/main.py.jinja2
Normal file
18
code/newsletter/N7/templates/project/main.py.jinja2
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import uvicorn
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
from {{ app_name }}.views import router
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
async def index():
|
||||||
|
return {"msg": "index"}
|
||||||
|
|
||||||
|
|
||||||
|
app.include_router(router)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
uvicorn.run(app)
|
||||||
8
code/newsletter/N7/templates/project/views.py.jinja2
Normal file
8
code/newsletter/N7/templates/project/views.py.jinja2
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from fastapi import APIRouter
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/{{ app_name }}/api")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/")
|
||||||
|
async def index():
|
||||||
|
return {"msg": "Hello, world"}
|
||||||
36
code/newsletter/N7/templates/web/base.html
Normal file
36
code/newsletter/N7/templates/web/base.html
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{% block title %}{% endblock %}</title>
|
||||||
|
<style>
|
||||||
|
.app {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
width: 1080px;
|
||||||
|
}
|
||||||
|
.halo {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
.data {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.data th, .data td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="app">
|
||||||
|
<p class="halo">👋 Halo! Welcome to my website!</p>
|
||||||
|
{% block body %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
code/newsletter/N7/templates/web/index.html
Normal file
13
code/newsletter/N7/templates/web/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}
|
||||||
|
{{ "Index" }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<p>Life is short, You need Python!</p>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
33
code/newsletter/N7/templates/web/user.html
Normal file
33
code/newsletter/N7/templates/web/user.html
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}
|
||||||
|
{{ "User" }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<main>
|
||||||
|
{% if users %}
|
||||||
|
<p>Users: </p>
|
||||||
|
<table class="data">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Id</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr scope="row">
|
||||||
|
<td>{{ user.id }}</td>
|
||||||
|
<td class="name">{{ user.name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor%}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<p>Whoops! Do you not seem to add any user?</p>
|
||||||
|
{% endif%}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
BIN
code/newsletter/N7/templates/word/base.docx
Normal file
BIN
code/newsletter/N7/templates/word/base.docx
Normal file
Binary file not shown.
BIN
code/newsletter/N7/templates/word/mars-cover.jpg
Normal file
BIN
code/newsletter/N7/templates/word/mars-cover.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 406 KiB |
42
code/newsletter/N7/web.py
Normal file
42
code/newsletter/N7/web.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import pathlib
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import uvicorn
|
||||||
|
from fastapi import FastAPI, Request
|
||||||
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||||
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
TEMPLATE = pathlib.Path(__file__).parent.joinpath("templates/web")
|
||||||
|
template = Jinja2Templates(directory=TEMPLATE)
|
||||||
|
|
||||||
|
users = [
|
||||||
|
dict(id=uuid.uuid4(), name="Steve Jobs"),
|
||||||
|
dict(id=uuid.uuid4(), name="Bill Gates"),
|
||||||
|
dict(id=uuid.uuid4(), name="Sundar Pichai"),
|
||||||
|
dict(id=uuid.uuid4(), name="Jeff Bezos"),
|
||||||
|
dict(id=uuid.uuid4(), name="100gle"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/", response_class=HTMLResponse)
|
||||||
|
async def index(request: Request):
|
||||||
|
ctx = dict(request=request)
|
||||||
|
return template.TemplateResponse("index.html", context=ctx)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/users/", response_class=HTMLResponse)
|
||||||
|
async def get_users(request: Request):
|
||||||
|
ctx = dict(request=request, users=users)
|
||||||
|
return template.TemplateResponse("user.html", context=ctx)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/users/{name}", response_class=HTMLResponse)
|
||||||
|
async def add_user(name: str):
|
||||||
|
users.append(dict(id=uuid.uuid4(), name=name))
|
||||||
|
return RedirectResponse("/users")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
uvicorn.run(app)
|
||||||
34
code/newsletter/N7/word.py
Normal file
34
code/newsletter/N7/word.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import pathlib
|
||||||
|
|
||||||
|
import docxtpl
|
||||||
|
import jinja2
|
||||||
|
from docx.shared import Cm
|
||||||
|
|
||||||
|
ROOT = pathlib.Path(__file__).parent.joinpath("templates/word")
|
||||||
|
fpath = ROOT / "base.docx"
|
||||||
|
docx = docxtpl.DocxTemplate(fpath)
|
||||||
|
env = jinja2.Environment(
|
||||||
|
lstrip_blocks=True,
|
||||||
|
trim_blocks=True,
|
||||||
|
)
|
||||||
|
cover = docxtpl.InlineImage(
|
||||||
|
docx,
|
||||||
|
image_descriptor=str(ROOT.joinpath("mars-cover.jpg")),
|
||||||
|
width=Cm(10),
|
||||||
|
height=Cm(6),
|
||||||
|
)
|
||||||
|
organizer = docxtpl.RichText()
|
||||||
|
organizer.add("Mars-3 太空文体部", url_id=docx.build_url_id("https://sspai.com"))
|
||||||
|
|
||||||
|
ctx = dict(
|
||||||
|
person_name="100gle",
|
||||||
|
date="宇宙元年338年13月32日 25时66分",
|
||||||
|
address="Mars-3 太空馆场",
|
||||||
|
party_name="摸鱼大会",
|
||||||
|
send_date="宇宙元年338年13月22日 36时90分",
|
||||||
|
cover=cover,
|
||||||
|
organizer=organizer,
|
||||||
|
)
|
||||||
|
docx.render(ctx, jinja_env=env)
|
||||||
|
|
||||||
|
docx.save(ROOT / "test.docx")
|
||||||
Reference in New Issue
Block a user