From 24cb0b88f71ecbe5efe3c4af2cbc071524653944 Mon Sep 17 00:00:00 2001 From: XingQue Date: Tue, 21 Jul 2026 03:56:11 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=A1=E6=A0=B8=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=BC=BA=20club=5Fid=20=E6=97=B6=E5=9B=9E=E8=90=BD=E6=97=A7?= =?UTF-8?q?=E8=A1=A8=EF=BC=8C=E9=81=BF=E5=85=8D=20hqsp=20500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 服务器未 migrate shop.0004 时不再因 Unknown column 打挂点单商品接口。 Co-authored-by: Cursor --- shop/services/shenhe_config.py | 104 ++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 20 deletions(-) diff --git a/shop/services/shenhe_config.py b/shop/services/shenhe_config.py index 44a7cb6..a3a7c32 100644 --- a/shop/services/shenhe_config.py +++ b/shop/services/shenhe_config.py @@ -1,43 +1,107 @@ """点单端商品展示 / 店铺审核模式:按俱乐部隔离。""" +import logging + +from django.db import OperationalError, ProgrammingError +from django.db.utils import DatabaseError + from jituan.constants import CLUB_ID_DEFAULT from shop.models import DianpuShangpinShenheShezhi +logger = logging.getLogger(__name__) + +_SCHEMA_ERRORS = (OperationalError, ProgrammingError, DatabaseError) + def _norm_club_id(club_id): return (club_id or CLUB_ID_DEFAULT).strip() or CLUB_ID_DEFAULT +def _legacy_row_values(*fields): + """ + 表尚未 migrate club_id 时:只查旧列,避免 SELECT club_id 导致 1054。 + """ + try: + return DianpuShangpinShenheShezhi.objects.values(*fields).first() + except _SCHEMA_ERRORS: + return None + + def get_or_create_shenhe_config(club_id): """获取或创建某俱乐部的审核展示配置。""" cid = _norm_club_id(club_id) - config, _ = DianpuShangpinShenheShezhi.objects.get_or_create( - club_id=cid, - defaults={ - 'kaiqi_shenhe': False, - 'zhi_kan_shenhe': True, - }, - ) - return config + try: + config, _ = DianpuShangpinShenheShezhi.objects.get_or_create( + club_id=cid, + defaults={ + 'kaiqi_shenhe': False, + 'zhi_kan_shenhe': True, + }, + ) + return config + except _SCHEMA_ERRORS as exc: + logger.error( + '审核配置表缺 club_id(请执行 migrate shop)。回落只读旧行。err=%s', + exc, + ) + # 尽量读旧全局行;读写接口若 save 仍会失败,需尽快 migrate + try: + obj = DianpuShangpinShenheShezhi.objects.defer('club_id').order_by('id').first() + if obj is not None: + return obj + except _SCHEMA_ERRORS: + pass + # 内存占位,避免后台整页 500 + from types import SimpleNamespace + return SimpleNamespace( + id=None, + club_id=cid, + kaiqi_shenhe=False, + zhi_kan_shenhe=True, + save=lambda *a, **k: (_ for _ in ()).throw( + RuntimeError('请先在服务器执行: python manage.py migrate shop') + ), + ) def is_zhi_kan_shenhe_enabled(club_id): """ 未绑店用户是否只看审核专用商品。 无配置时默认 True,保持历史行为。 + 未 migrate club_id 时回落旧表,绝不因缺列导致 /hqsp 500。 """ - config = DianpuShangpinShenheShezhi.query.filter( - club_id=_norm_club_id(club_id) - ).first() - if not config: - return True - return bool(getattr(config, 'zhi_kan_shenhe', True)) + try: + config = DianpuShangpinShenheShezhi.query.filter( + club_id=_norm_club_id(club_id) + ).first() + if not config: + return True + return bool(getattr(config, 'zhi_kan_shenhe', True)) + except _SCHEMA_ERRORS as exc: + logger.error( + 'is_zhi_kan_shenhe_enabled 缺列回落(请 migrate shop)。err=%s', + exc, + ) + row = _legacy_row_values('zhi_kan_shenhe') + if not row: + return True + return bool(row.get('zhi_kan_shenhe', True)) def is_kaiqi_shenhe_enabled(club_id): """店铺发布商品是否需平台审核。无配置默认 False。""" - config = DianpuShangpinShenheShezhi.query.filter( - club_id=_norm_club_id(club_id) - ).first() - if not config: - return False - return bool(config.kaiqi_shenhe) + try: + config = DianpuShangpinShenheShezhi.query.filter( + club_id=_norm_club_id(club_id) + ).first() + if not config: + return False + return bool(config.kaiqi_shenhe) + except _SCHEMA_ERRORS as exc: + logger.error( + 'is_kaiqi_shenhe_enabled 缺列回落(请 migrate shop)。err=%s', + exc, + ) + row = _legacy_row_values('kaiqi_shenhe') + if not row: + return False + return bool(row.get('kaiqi_shenhe', False))