在 sqlalchemy 中提供模型类级别的验证
Posted
技术标签:
【中文标题】在 sqlalchemy 中提供模型类级别的验证【英文标题】:Providing validation on model class level in sqlalchemy 【发布时间】:2018-11-13 09:39:16 【问题描述】:我试图在读取 xlsx 文件后将数据插入到我的 postgres 表中。 在将 xlsx 工作表数据插入表之前,我需要对其进行验证。
我正在处理熊猫数据框df = pd.read_excel('/Users/ankitg3-mac/Downloads/medical_plans/%s' % filename)
我使用 sqlalchemy 作为我的 ORM 工具。
我的模型课:
class MedicalPlan(Base):
__tablename__ = "medical_plans"
id = Column(Integer, nullable=False , primary_key=True)
issuer_id = Column(Integer, ForeignKey('issuers.id'), nullable=False)
service_area_id = Column(Integer)
name = Column(String)
on_exchange = Column(Boolean)
off_exchange = Column(Boolean)
starting_percentage_fpl = Column(REAL, nullable=False , default=0)
ending_percentage_fpl = Column(REAL, nullable=False, default=0)
metal_level_name = Column(String)
network_type = Column(String)
type = Column(String)
is_age_29_plan = Column(Boolean)
original_medicare = Column(Boolean)
default_bhp = Column(Boolean, default=False)
sort_rank_override = Column(Integer)
recommended = Column(Boolean, default=False)
comparable_individual_plan_id_trash = Column(Integer)
group_or_individual_plan_type = Column(String)
hios_plan_identifier = Column(String)
我正在使用字典列表进行批量插入。
conn.execute(MedicalPlan.__table__.insert(), medicalPlan_dict)
我的 medicalPlan_dict 如下所示:
[u'default_bhp': False, u'price_period': u'Monthly', u'plan_description': '', u'sbc_download_url': '', u'price_note': '', u'starting_percentage_fpl': 0, u'is_uhc_plan': False, 'issuer_id': 440, u'part_b_deductible': '', u'promotional_label': '', u'metal_level_name': u'Silver', u'network_url': '', u'group_or_individual_plan_type': u'Group', u'treatment_cost_calculator_url': '', u'hios_plan_identifier': u'99844RI1800001', u'original_medicare': False, u'part_d_prescription_coverage': '', u'recommended': False, u'off_exchange': True, u'is_age_29_plan': False, u'type': u'MetalPlan', u'ending_percentage_fpl': 0, u'plan_detail_footer': '', u'formulary_url': '', u'plan_detail_items': '', u'highlight_6': '', u'highlight_4': '', u'highlight_5': '', u'hsa_eligible': False, u'highlight_3': u'PCP 20% coinsurance', u'highlight_1': u'Silver', u'name': u'WI 80 INDEMNITY 18 OPTION 1 SILVER RX $10/45/90/25%', u'network_description': '', u'plan_detail_header': '', 'service_area_id': 1, u'data_sourced_from': u'uhc', u'plan_year': 2018, u'highlight_2': u'Indemnity', u'on_exchange': False, u'network_type': u'Indemnity', u'default_bhp': False, u'price_period': u'Monthly', u'plan_description': '', u'sbc_download_url': '', u'price_note': '', u'starting_percentage_fpl': 0, u'is_uhc_plan': False, 'issuer_id': 484, u'part_b_deductible': '', u'promotional_label': '', u'metal_level_name': u'Silver', u'network_url': '', u'group_or_individual_plan_type': u'Group', u'treatment_cost_calculator_url': '', u'hios_plan_identifier': u'99806CAAUSJ-TMP1', u'original_medicare': False, u'part_d_prescription_coverage': '', u'recommended': False, u'off_exchange': True, u'is_age_29_plan': False, u'type': u'MetalPlan', u'ending_percentage_fpl': 0, u'plan_detail_footer': '', u'formulary_url': '', u'plan_detail_items': '', u'highlight_6': '', u'highlight_4': '', u'highlight_5': '', u'hsa_eligible': False, u'highlight_3': u'PCP 20% coinsurance', u'highlight_1': u'Silver', u'name': u'WI 80 INDEMNITY 18 OPTION 1 SILVER RX $10/45/90/25%', u'network_description': '', u'plan_detail_header': '', 'service_area_id': 1, u'data_sourced_from': u'uhc', u'plan_year': 2018, u'highlight_2': u'Indemnity', u'on_exchange': False, u'network_type': u'Indemnity', u'default_bhp': False, u'price_period': u'Monthly', u'plan_description': '', u'sbc_download_url': '', u'price_note': '', u'starting_percentage_fpl': 0, u'is_uhc_plan': False, 'issuer_id': 440, u'part_b_deductible': '', u'promotional_label': '', u'metal_level_name': u'Silver', u'network_url': '', u'group_or_individual_plan_type': u'Group', u'treatment_cost_calculator_url': '', u'hios_plan_identifier': u'99844RI1800002', u'original_medicare': False, u'part_d_prescription_coverage': '', u'recommended': False, u'off_exchange': True, u'is_age_29_plan': False, u'type': u'MetalPlan', u'ending_percentage_fpl': 0, u'plan_detail_footer': '', u'formulary_url': '', u'plan_detail_items': '', u'highlight_6': '', u'highlight_4': '', u'highlight_5': '', u'hsa_eligible': False, u'highlight_3': u'PCP 20% coinsurance', u'highlight_1': u'Silver', u'name': u'WI 80 INDEMNITY 18 OPTION 1 SILVER RX $10/45/90/25%', u'network_description': '', u'plan_detail_header': '', 'service_area_id': 1, u'data_sourced_from': u'uhc', u'plan_year': 2018, u'highlight_2': u'Indemnity', u'on_exchange': False, u'network_type': u'Indemnity']
在将数据插入表之前,我需要对其进行验证。 我阅读了有关 sqlalchemy 验证的信息,并尝试了类似下面的内容,假设它会处理模型级别的验证。
@validates('hios_plan_identifier')
def validate_hios_plan_identifier(self, key, hios_plan_identifier):
assert '/\A(\d5[A-Z]2[a-zA-Z0-9]3,7-TMP|\d5[A-Z]2\d3,7(\-?\d2)*)\z/,' in hios_plan_identifier
return hios_plan_identifier
我需要对每个变量进行少量验证。只应插入通过的行。
我不确定如何在模型级别进行验证。我怎样才能做到这一点。
【问题讨论】:
虽然这有点明显,但您应该提供更多关于它如何不起作用的信息。没有明确问题陈述的问题通常没有用处。 更新了整个问题。希望你能找到我卡住的地方 这一行:'/\A(\d5[A-Z]2[a-zA-Z0-9]3,7-TMP|\d5[A-Z]2\d3,7(\-?\d2)*)\z/,' in hios_plan_identifier
。 '/\A(\d5[A-Z]2[a-zA-Z0-9]3,7-TMP|\d5[A-Z]2\d3,7(\-?\d2)*)\z/,'
不是正则表达式,它只是一个普通字符串。除非整个字符串在 hios_plan_identifier
的值中,否则该断言不会评估为 True。
是re.search()
你在找什么?
我想知道 ORM 级别的验证是否也适用于批量插入。
【参考方案1】:
两种选择:
在列上添加CheckConstraint
并在那里添加您的正则表达式,请参阅
https://www.postgresql.org/docs/9.3/functions-matching.html 。无论您以何种方式将数据放入数据库,这都有效。
使用 here 演示的基于事件的验证,创建要插入的对象列表并使用 session.add_all()
进行批量插入。
【讨论】:
以上是关于在 sqlalchemy 中提供模型类级别的验证的主要内容,如果未能解决你的问题,请参考以下文章
基础入门_Python-模块和包.深入SQLAlchemy之列级别约束与表级别约束?