From 7abdc336b74dcdb5d7014fad971ce42e8714623b Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 3 Jun 2026 17:24:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(entcms):=20=E9=87=8D=E5=86=99=E6=89=80?= =?UTF-8?q?=E6=9C=89=E6=95=B0=E6=8D=AE=E5=BA=93=E6=93=8D=E4=BD=9C=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20async=20with=20context=20manager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _get_db() 返回的是 async context manager,不是 sor 对象。 所有函数都错误地直接调用 sor.R/C/U/D,导致 AttributeError。 修正为正确模式: db = DBPools() async with db.sqlorContext(DBNAME) as sor: await sor.R('table', ns) 影响函数: - cms_content CRUD (4个) - cms_categories CRUD (4个) + get_category_options - cms_leads CRUD (4个) + submit_lead - cms_sections CRUD (4个) + get_visible_sections - cms_site_config CRUD (4个) + get_site_config - get_published_content, get_latest_news, get_content_detail - submit_content_for_approval --- entcms/entcms/init.py | 231 +++++++++++++++++++++++------------------- 1 file changed, 127 insertions(+), 104 deletions(-) diff --git a/entcms/entcms/init.py b/entcms/entcms/init.py index d955d22..c1b6171 100644 --- a/entcms/entcms/init.py +++ b/entcms/entcms/init.py @@ -5,6 +5,7 @@ entcms - 企业CMS系统模块 import json from ahserver.serverenv import ServerEnv from appPublic.uniqueID import getID +from sqlor.dbpools import DBPools MODULE_NAME = "entcms" MODULE_VERSION = "1.0.0" @@ -12,152 +13,165 @@ MODULE_VERSION = "1.0.0" DBNAME = "entcms" -def _get_db(): - """获取数据库上下文""" - from sqlor.dbpools import DBPools - return DBPools().sqlorContext(DBNAME) - - # ===== CMS Content CRUD ===== async def cms_content_list(ns=None): """查询内容列表""" - sor = _get_db() - ns = ns or {} - ns.setdefault('sort', 'sort_order asc, created_at desc') - rows = await sor.R('cms_content', ns) - total = len(rows) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = ns or {} + ns.setdefault('sort', 'sort_order asc, created_at desc') + rows = await sor.R('cms_content', ns) + total = len(rows) return {'rows': rows, 'total': total} async def cms_content_create(data): """创建内容""" - sor = _get_db() - data['id'] = getID() - await sor.C('cms_content', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + data['id'] = getID() + await sor.C('cms_content', data) return data async def cms_content_update(data): """更新内容""" - sor = _get_db() - await sor.U('cms_content', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.U('cms_content', data) return data async def cms_content_delete(data): """删除内容""" - sor = _get_db() - await sor.D('cms_content', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.D('cms_content', data) return data # ===== CMS Categories CRUD ===== async def cms_categories_list(ns=None): """查询分类列表""" - sor = _get_db() - ns = ns or {} - ns.setdefault('sort', 'sort_order asc') - rows = await sor.R('cms_categories', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = ns or {} + ns.setdefault('sort', 'sort_order asc') + rows = await sor.R('cms_categories', ns) return {'rows': rows, 'total': len(rows)} async def cms_categories_create(data): - sor = _get_db() - data['id'] = getID() - await sor.C('cms_categories', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + data['id'] = getID() + await sor.C('cms_categories', data) return data async def cms_categories_update(data): - sor = _get_db() - await sor.U('cms_categories', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.U('cms_categories', data) return data async def cms_categories_delete(data): - sor = _get_db() - await sor.D('cms_categories', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.D('cms_categories', data) return data async def get_category_options(content_type=None): """获取分类下拉选项""" - sor = _get_db() - ns = {'sort': 'sort_order asc'} - if content_type: - ns['content_type'] = content_type - rows = await sor.R('cms_categories', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = {'sort': 'sort_order asc'} + if content_type: + ns['content_type'] = content_type + rows = await sor.R('cms_categories', ns) options = [{'value': r['id'], 'text': r['name']} for r in rows] return options # ===== CMS Leads CRUD ===== async def cms_leads_list(ns=None): - sor = _get_db() - ns = ns or {} - ns.setdefault('sort', 'created_at desc') - rows = await sor.R('cms_leads', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = ns or {} + ns.setdefault('sort', 'created_at desc') + rows = await sor.R('cms_leads', ns) return {'rows': rows, 'total': len(rows)} async def cms_leads_create(data): - sor = _get_db() - data['id'] = getID() - await sor.C('cms_leads', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + data['id'] = getID() + await sor.C('cms_leads', data) return data async def cms_leads_update(data): - sor = _get_db() - await sor.U('cms_leads', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.U('cms_leads', data) return data async def cms_leads_delete(data): - sor = _get_db() - await sor.D('cms_leads', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.D('cms_leads', data) return data async def submit_lead(data): """公开接口 - 网站访客提交线索""" - sor = _get_db() - data['id'] = getID() - data.setdefault('status', 'new') - data.setdefault('source', 'website') - await sor.C('cms_leads', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + data['id'] = getID() + data.setdefault('status', 'new') + data.setdefault('source', 'website') + await sor.C('cms_leads', data) return {'status': 'ok', 'id': data['id']} # ===== CMS Sections CRUD ===== async def cms_sections_list(ns=None): - sor = _get_db() - ns = ns or {} - ns.setdefault('sort', 'sort_order asc') - rows = await sor.R('cms_sections', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = ns or {} + ns.setdefault('sort', 'sort_order asc') + rows = await sor.R('cms_sections', ns) return {'rows': rows, 'total': len(rows)} async def cms_sections_create(data): - sor = _get_db() - data['id'] = getID() - await sor.C('cms_sections', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + data['id'] = getID() + await sor.C('cms_sections', data) return data async def cms_sections_update(data): - sor = _get_db() - await sor.U('cms_sections', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.U('cms_sections', data) return data async def cms_sections_delete(data): - sor = _get_db() - await sor.D('cms_sections', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.D('cms_sections', data) return data async def get_visible_sections(): """获取所有可见栏目(公开接口)""" - sor = _get_db() - ns = {'is_visible': '1', 'sort': 'sort_order asc'} - rows = await sor.R('cms_sections', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = {'is_visible': '1', 'sort': 'sort_order asc'} + rows = await sor.R('cms_sections', ns) import json as _json for r in rows: for field in ['display_config', 'style_config', 'static_content']: @@ -169,39 +183,44 @@ async def get_visible_sections(): # ===== CMS Site Config CRUD ===== async def cms_site_config_list(ns=None): - sor = _get_db() - ns = ns or {} - ns.setdefault('sort', 'config_group asc, sort_order asc') - rows = await sor.R('cms_site_config', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = ns or {} + ns.setdefault('sort', 'config_group asc, sort_order asc') + rows = await sor.R('cms_site_config', ns) return {'rows': rows, 'total': len(rows)} async def cms_site_config_create(data): - sor = _get_db() - data['id'] = getID() - await sor.C('cms_site_config', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + data['id'] = getID() + await sor.C('cms_site_config', data) return data async def cms_site_config_update(data): - sor = _get_db() - await sor.U('cms_site_config', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.U('cms_site_config', data) return data async def cms_site_config_delete(data): - sor = _get_db() - await sor.D('cms_site_config', data) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + await sor.D('cms_site_config', data) return data async def get_site_config(group=None): """获取站点配置(公开接口)""" - sor = _get_db() - ns = {'sort': 'sort_order asc'} - if group: - ns['config_group'] = group - rows = await sor.R('cms_site_config', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = {'sort': 'sort_order asc'} + if group: + ns['config_group'] = group + rows = await sor.R('cms_site_config', ns) result = {} for r in rows: g = r.get('config_group', '') @@ -214,11 +233,12 @@ async def get_site_config(group=None): # ===== Public Content APIs ===== async def get_published_content(content_type=None, limit=10): """获取已发布内容(公开接口)""" - sor = _get_db() - ns = {'status': 'published', 'sort': 'sort_order asc, published_at desc'} - if content_type: - ns['content_type'] = content_type - rows = await sor.R('cms_content', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = {'status': 'published', 'sort': 'sort_order asc, published_at desc'} + if content_type: + ns['content_type'] = content_type + rows = await sor.R('cms_content', ns) if limit: rows = rows[:limit] return rows @@ -226,36 +246,39 @@ async def get_published_content(content_type=None, limit=10): async def get_latest_news(limit=2): """获取最新新闻(公开接口)""" - sor = _get_db() - ns = {'status': 'published', 'content_type': 'news', 'sort': 'published_at desc'} - rows = await sor.R('cms_content', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = {'status': 'published', 'content_type': 'news', 'sort': 'published_at desc'} + rows = await sor.R('cms_content', ns) return rows[:limit] async def get_content_detail(content_id): """获取内容详情(公开接口)""" - sor = _get_db() - ns = {'id': content_id, 'status': 'published'} - rows = await sor.R('cms_content', ns) + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + ns = {'id': content_id, 'status': 'published'} + rows = await sor.R('cms_content', ns) return rows[0] if rows else None # ===== Submit for approval ===== async def submit_content_for_approval(content_id, title, applicant_id): """提交内容审批(调用dingdingflow)""" - # 更新内容状态为pending - sor = _get_db() - await sor.U('cms_content', {'id': content_id, 'status': 'pending'}) - # 调用dingdingflow的submit_approval - try: - from dingdingflow.init import submit_approval - result = await submit_approval('content_publish', content_id, title, applicant_id) - # 保存审批ID - if result and result.get('approval_id'): - await sor.U('cms_content', {'id': content_id, 'approval_id': result['approval_id']}) - return result - except ImportError: - return {'status': 'error', 'message': 'dingdingflow模块未安装'} + db = DBPools() + async with db.sqlorContext(DBNAME) as sor: + # 更新内容状态为pending + await sor.U('cms_content', {'id': content_id, 'status': 'pending'}) + # 调用dingdingflow的submit_approval + try: + from dingdingflow.init import submit_approval + result = await submit_approval('content_publish', content_id, title, applicant_id) + # 保存审批ID + if result and result.get('approval_id'): + await sor.U('cms_content', {'id': content_id, 'approval_id': result['approval_id']}) + return result + except ImportError: + return {'status': 'error', 'message': 'dingdingflow模块未安装'} def load_entcms():