1、建立环境
windows下
cd .\cards-backend\
python -m venv venv
.\venv\Scripts\Activate.ps1
老样子,记得切到venv下面去
=======================================================
2、安装界面库
pip3 install nicegui先装nicgui
from nicegui import ui
ui.label('Hello NiceGUI!')
ui.run()测试用代码

好了,没问题了
=======================================================
3、安装数据库ORM库,小乌龟
pip3 install tortoise-orm定义模型:models.py
from tortoise.models import Model
from tortoise import fields
class Cards(Model):
id = fields.IntField(pk=True)
study_id = fields.TextField()
front_cover_image = fields.TextField()
front_cover_llm_prompt = fields.TextField()
cn_text = fields.TextField()
fr_text = fields.TextField()
pinyin_text = fields.TextField()
create_date = fields.DatetimeField(auto_now_add=True)
update_date = fields.DatetimeField(auto_now=True)from tortoise import Tortoise, run_async
from models import Cards
async def init():
# Here we create a SQLite DB using file "db.sqlite3"
# also specify the app name of "models"
# which contain models from "app.models"
await Tortoise.init(
db_url='sqlite://db.sqlite3',
modules={'models': ['models']}
)
# Generate the schema
await Tortoise.generate_schemas()
# Create instance by save
card = Cards(study_id='1.1.1',
front_cover_image="\\images\\p2888293790.jpeg",
front_cover_llm_prompt="",
cn_text="你好!你好!",
fr_text="Bonjour!Bonjour!",
pinyin_text="/nǐ/hǎo! /nǐ/hǎo!")
await card.save()
await Tortoise.close_connections()
# run_async is a helper function to run simple async Tortoise scripts.
run_async(init())做一个数据库的初始化的脚本
接着,初始化数据库本身:
python init_db.py
用Dbearver打开

很好,用数据库来管理就会方便很多
=======================================================
4、移植一个最基础版本的编辑界面:
from typing import List
import models
from tortoise import Tortoise
from nicegui import app, ui
async def init_db() -> None:
await Tortoise.init(db_url='sqlite://db.sqlite3', modules={'models': ['models']})
async def close_db() -> None:
await Tortoise.close_connections()
app.on_startup(init_db)
app.on_shutdown(close_db)
@ui.refreshable
async def list_of_cards() -> None:
async def delete(card: models.Cards) -> None:
await card.delete()
list_of_cards.refresh()
cards: List[models.Cards] = await models.Cards.all()
print(cards)
for card in reversed(cards):
with ui.card():
with ui.row().classes('items-center'):
ui.input('study_id', on_change=card.save) \
.bind_value(card, 'study_id').on('blur', list_of_cards.refresh)
ui.input('front_cover_image', on_change=card.save) \
.bind_value(card, 'front_cover_image').on('blur', list_of_cards.refresh).classes('w-20')
ui.input('prompt', on_change=card.save) \
.bind_value(card, 'front_cover_llm_prompt').on('blur', list_of_cards.refresh)
ui.input('cn_text', on_change=card.save) \
.bind_value(card, 'cn_text').on('blur', list_of_cards.refresh)
ui.input('fr_text', on_change=card.save) \
.bind_value(card, 'fr_text').on('blur', list_of_cards.refresh)
ui.input('pinyin_text', on_change=card.save) \
.bind_value(card, 'pinyin_text').on('blur', list_of_cards.refresh)
ui.button(icon='delete', on_click=lambda u=card: delete(u)).props('flat')
@ui.page('/')
async def index():
async def create() -> None:
await models.Cards.create(name=name.value, front_cover_image='')
name.value = ''
front_cover_image.value = None
list_of_cards.refresh()
with ui.column().classes('mx-auto'):
with ui.row().classes('w-full items-center px-4'):
name = ui.input(label='Name')
front_cover_image = ui.input(label='front_cover_image').classes('w-20')
ui.button(on_click=create, icon='add').props('flat').classes('ml-auto')
await list_of_cards()
ui.run()
=======================================================
5、引入模板生成机制,生成静态的html5页面
pip3 install Jinja2然后建立模板:
{% for card in cards %}
<!-- Slides -->
<div class="swiper-slide">
<img src="{{ card.front_cover_image }}" alt="Card 1 Image">
<span class="row">
<span class="lang">🇨🇳</span>
<p class="in-speak">{{ card.cn_text }}</p>
</span>
<span class="row">
<span class="lang">🇫🇷</span>
<p class="in-speak">{{ card.fr_text }}</p>
</span>
</div>
{% endfor %}昨天的工作成果里,我使用了swiper这个库来建立上下滑动的东西
然后今天我把html这部分模板化掉
from jinja2 import Environment, FileSystemLoader
# 加载模板文件
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('index_template.html')python里加载模板文件

在这里加入新的按钮

按钮对应新的渲染逻辑:
async def build_html() -> None:
print("I am in build_html()")
cards: List[models.Cards] = await models.Cards.all()
print(cards)
# 渲染模板
html_output = template.render(cards=cards)
# 将渲染后的结果写入文件(可选)
with open('index.html', 'w') as file:
file.write(html_output)加载数据库的所有卡片,并且渲染新的index.html
报错:'gbk' codec can't encode character '\U0001f1e8' in position 1763: illegal multibyte sequence
修改open部分:

with open('index.html', 'w',encoding='utf-8') as file:
file.write(html_output)问题解决
看一下生成的index.html

卧槽,效果真好
OK,这样以后就不用手动去管理这个东西了
==========================================
6、工作流
先维护数据库:

生成好对应的图片
进入页面点击最右边的生成页面



进入刚才生成的index.html刷新查看结果
之后再写一个发布的脚本就可以了
=============================================
7、待优化
豆包那边生成图片到这个具体的句子的关联的过程,以及翻译的过程,是可以将存入数据库的过程再自动化一些的
这样就可以制作上千条句子的对应五六个国家语言的场景卡片了