95 lines
3.3 KiB
Python
95 lines
3.3 KiB
Python
# coding=utf-8
|
||
"""特征模板表(总服务器权威;SQLite 可缓存镜像)。
|
||
|
||
一条记录 = 某道菜的一张参考图特征向量,用于识别匹配。
|
||
"""
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import Column, DateTime, Float, ForeignKey, Index, Integer, String, Text
|
||
from sqlalchemy.orm import relationship
|
||
from sqlalchemy.sql import func
|
||
|
||
from dao.db import Base
|
||
|
||
|
||
class GlobalTemplate(Base):
|
||
__tablename__ = 'global_templates'
|
||
|
||
id = Column(Integer, primary_key=True, autoincrement=True, comment='主键ID')
|
||
category_id = Column(
|
||
Integer,
|
||
ForeignKey('dish_categories.id', ondelete='RESTRICT'),
|
||
nullable=False,
|
||
comment='关联菜品ID',
|
||
)
|
||
# Base64(float32 特征向量);跨 MySQL/SQLite 兼容,读写见 dao.feature_codec
|
||
feature_blob = Column(Text, nullable=False, comment='特征向量 Base64(float32)')
|
||
# 总服务器优先存可访问 URL;本地缓存可为文件路径
|
||
image_url = Column(String(512), nullable=True, comment='模板图片 URL 或路径')
|
||
thumbnail_url = Column(String(512), nullable=True, comment='缩略图 URL 或路径')
|
||
source_base_id = Column(
|
||
Integer,
|
||
ForeignKey('bases.id', ondelete='SET NULL'),
|
||
nullable=True,
|
||
comment='上传该模板的基地ID',
|
||
)
|
||
confidence = Column(Float, nullable=False, default=1.0, server_default='1', comment='质量分/置信度')
|
||
is_active = Column(Integer, nullable=False, default=1, server_default='1', comment='是否生效:1启用 0废弃')
|
||
create_time = Column(
|
||
DateTime,
|
||
nullable=False,
|
||
default=datetime.now,
|
||
server_default=func.now(),
|
||
comment='创建时间',
|
||
)
|
||
update_time = Column(
|
||
DateTime,
|
||
nullable=False,
|
||
default=datetime.now,
|
||
server_default=func.now(),
|
||
onupdate=datetime.now,
|
||
comment='更新时间(增量同步关键)',
|
||
)
|
||
|
||
category = relationship('DishCategory', back_populates='templates')
|
||
source_base = relationship('BaseInfo', back_populates='templates', foreign_keys=[source_base_id])
|
||
|
||
__table_args__ = (
|
||
Index('idx_gt_category', 'category_id'),
|
||
Index('idx_gt_update_time', 'update_time'),
|
||
Index('idx_gt_active', 'is_active'),
|
||
Index('idx_gt_active_update', 'is_active', 'update_time'),
|
||
Index('idx_gt_source_base', 'source_base_id'),
|
||
)
|
||
|
||
# 兼容旧代码属性名
|
||
@property
|
||
def image_path(self):
|
||
return self.image_url
|
||
|
||
@image_path.setter
|
||
def image_path(self, value):
|
||
self.image_url = value
|
||
|
||
@property
|
||
def thumbnail_path(self):
|
||
return self.thumbnail_url
|
||
|
||
@thumbnail_path.setter
|
||
def thumbnail_path(self, value):
|
||
self.thumbnail_url = value
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'category_id': self.category_id,
|
||
'feature_blob': self.feature_blob,
|
||
'image_url': self.image_url,
|
||
'thumbnail_url': self.thumbnail_url,
|
||
'source_base_id': self.source_base_id,
|
||
'confidence': self.confidence,
|
||
'is_active': self.is_active,
|
||
'create_time': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if self.create_time else None,
|
||
'update_time': self.update_time.strftime('%Y-%m-%d %H:%M:%S') if self.update_time else None,
|
||
}
|