如何构建支持多校区的Python站点配置类?
问题描述
我为公司IT部门开发了一款展示待领取笔记本电脑的Web应用,总部要求将其适配为可跨多站点使用的版本,部分站点包含多个校区。此前我使用全局变量存储站点配置并保存至.ini文件,启动时加载,但该方案已不再适用。
我计划将配置封装为类的属性,根据客户端访问路径实例化类并从.ini文件对应节加载配置值。但部分站点没有多个校区,需避免加载不存在的信息。我考虑用一个关联的子类来管理校区名称和设备归还审批人信息,但不清楚该实现方式的名称及具体做法,作为编程新手,希望获得相关技术指导。
我尝试编写的初始代码如下:
# Site class class site: name = "" # Name of the site siteID = "" # Site ID (also path of site specific noticeboard). key = "" # Helpdesk API Key url = "" # Helpdesk URL campusCount = "" # Number of campuses XCampusName = "" # Name of campus "X". XCampusApprover = "" # Name of campus "X" return approver. collectionName = "" # Name of collection status in helpdesk. approvalName = "" # Name of approval status in helpdesk.
解决方案
你要的这种实现方式叫做组合(Composition)——不是用子类继承,而是把校区作为站点的一个独立组成模块来管理,这种方式比继承更灵活,也更贴合你的业务场景。下面是具体的实现步骤和代码示例:
1. 定义独立的校区类
先创建一个专门的Campus类,只负责存储单个校区的核心信息:
class Campus: def __init__(self, name: str, approver: str): self.name = name # 校区名称 self.approver = approver # 设备归还审批人
2. 修改站点类,用组合方式管理校区
把原来site类里的campusCount、XCampusName、XCampusApprover这些硬编码字段,替换成一个存储Campus实例的列表。空列表就代表该站点没有多校区,完全不需要额外处理:
class Site: def __init__(self): self.name = "" # 站点名称 self.site_id = "" # 站点ID(对应站点公告板路径) self.helpdesk_key = "" # 服务台API密钥 self.helpdesk_url = "" # 服务台URL self.campuses = [] # 校区列表,无校区则为空 self.collection_status_name = "" # 服务台中"待领取"状态的名称 self.approval_status_name = "" # 服务台中"已审批"状态的名称
3. 从.ini文件加载配置的逻辑
用Python内置的configparser模块读取配置文件,先加载站点的基础配置,再遍历检查是否存在该站点对应的校区配置节,存在则实例化Campus并加入列表:
假设你的.ini文件结构如下:
[Site1] name = 总部站点 site_id = HQ helpdesk_key = abc123 helpdesk_url = https://helpdesk.example.com/hq collection_status_name = 待领取 approval_status_name = 已审批 [Site1.Campus1] name = 东校区 approver = 张三 [Site1.Campus2] name = 西校区 approver = 李四 [Site2] name = 分站点 site_id = BranchA helpdesk_key = def456 helpdesk_url = https://helpdesk.example.com/branchA collection_status_name = 待领取 approval_status_name = 已审批
对应的加载代码:
import configparser def load_site_config(site_id: str, config_path: str) -> Site: config = configparser.ConfigParser() config.read(config_path) site = Site() # 加载站点基础配置 site_section = site_id site.name = config.get(site_section, "name") site.site_id = config.get(site_section, "site_id") site.helpdesk_key = config.get(site_section, "helpdesk_key") site.helpdesk_url = config.get(site_section, "helpdesk_url") site.collection_status_name = config.get(site_section, "collection_status_name") site.approval_status_name = config.get(site_section, "approval_status_name") # 加载校区配置(如果存在) campus_section_prefix = f"{site_id}.Campus" campus_index = 1 while True: campus_section = f"{campus_section_prefix}{campus_index}" if campus_section not in config: break campus_name = config.get(campus_section, "name") campus_approver = config.get(campus_section, "approver") site.campuses.append(Campus(campus_name, campus_approver)) campus_index += 1 return site
4. 使用示例
# 加载总部站点配置(包含2个校区) hq_site = load_site_config("Site1", "config.ini") print(f"站点名称: {hq_site.name}") print(f"校区数量: {len(hq_site.campuses)}") for campus in hq_site.campuses: print(f"校区: {campus.name}, 审批人: {campus.approver}") # 加载分站点配置(无校区) branch_site = load_site_config("Site2", "config.ini") print(f"\n站点名称: {branch_site.name}") print(f"校区数量: {len(branch_site.campuses)}") # 输出0
为什么选择组合而非子类?
- 灵活性高:站点与校区是"包含"关系,不是"继承"关系,站点可以有0个或多个校区,完全匹配你的业务场景
- 代码解耦:校区的逻辑独立维护,后续修改校区属性或行为,不会影响站点类的代码
- 符合开闭原则:新增校区类型或站点类型时,无需修改原有代码,只需新增对应类即可
内容的提问来源于stack exchange,提问作者Scobbo
相关产品推荐
相关产品推荐

