如何定义接受来自自定义查询工厂的输入的自定义 WTForms 验证器类?

问题描述

我正在尝试定义一个自定义 WTForms 验证器,我可以使用它来根据在同一表单的多个字段中输入的数据组合检查数据库中是否已存在记录。

我被卡住了,不知道该怎么做。我也是编程新手,仍在尝试了解 Python,老实说,herehere 中的一些东西超出了我目前的理解范围。

所以,模型在这里定义:

class Data1(Base):
__tablename__ = 'data1'
id = Column(Integer,primary_key=True,unique=True,nullable=False)
description = Column(String,nullable=False)


class Data2(Base):
    __tablename__ = 'data2'
    id = Column(Integer,nullable=False)
    description = Column(String,nullable=False)


class Data3(Base):
    __tablename__ = 'data3'
    id = Column(Integer,nullable=False)
    data1_id = Column(Integer,ForeignKey('data1.id'),nullable=False)
    data2_id = Column(Integer,ForeignKey('data2.id'),nullable=False)

此处的示例数据:

session.add_all([
Data1(id=1,description='a'),Data1(id=2,description='b'),Data1(id=3,description='c'),Data2(id=1,description='aa'),Data2(id=2,description='bb'),Data2(id=3,description='cc'),Data3(id=4,data1_id=1,data2_id=1,description='all first entries of data 1 & 2')
])

session.commit()

问题在我下面的评论中定义:

# Define validator class. This needs to be defined outside the form deFinition since it will be used in a lot of forms.
class Uniqueness(object):
    def __init__(self,message=None,dbqry=None):
        if not message:
            message = u'Duplicate field combination detected!'
        self.message = message
        self.dbqry = dbqry

    def __call__(self):
        if self.dbqry:
            raise ValidationError(self.message)


# Instantiate validator
uniqueness = Uniqueness


# Define query factory. This needs to be defined outside the form deFinition since it will be used in a lot of forms.
def qry(dbModel,frm,*atts):
    # Sample target filter to pass on the query at the bottom of this function:
    # fl = [
    #       Data3.data1_id == Myform.data1_id.data
    #       Data3.data2_id == Myform.data2_id.data
    #       Data3.description == Myform.description.data
    #       ]
    # Question1: Referring to the custom validator example [here][3] where 'self' and '.data'
    # attributes were used when validator was defined within form class deFinition,# Is my adaptation sample above suited to the purpose,I am trying to achieve here?
    # If not,then how should I go about this?
    # Question2: How can I generate same list as above which I can pass on to the filter part
    # of the query statement at the bottom of this function?
    # Below is my attempt to answer this:
    fl = []
    for att in atts:
        try:
            hasattr(dbModel,'att')
        except AttributeError:
            raise AttributeError(f'{dbModel}.{att} is invalid.')
        else:
            mdl_att = str(getattr(dbModel,att))
            # Question3: This is probably wrong since I would then have to use 'eval' at some point right?
            # I don't want to use 'eval' if possible.
        try:
            hasattr(frm,'att')
        except AttributeError:
            raise AttributeError(f'{frm}.{att} is invalid.')
        else:
            frm_att = str(getattr(frm,att))
            # Question4: If the '.data' attribute from the intended output of the 'fl' example above is indeed required,# How would I state it here?
        # Below is suppose to create the list defined above,but I reckon this will create a string 
        # which I can't use.
        # Question6: What is the better way of doing this?
        fl.append(mdl_att + '==' + frm_att)

    # Query the dbModel to check if a record exists with the data combination as defined in fl filter.
    return session.query(dbModel).filter(fl).first()


# Instantiate the query here?
# Question5: 'MyForm' is used before the form class deFinition,How can this be addressed?
dbQry = qry(Data3,MyForm,'data1_id','data2_id','description')


# Define the form
class MyForm(FlaskForm):
    # Question5: Or perhaps instantiate inside the form deFinition?
    # dbQry = qry(Data3,'description')
    # if it should be here then how to properly do it?
    choices1 = session.query(Data1.id,Data1.description).all()
    data1_id = SelectField('Select Field 1',choices=choices1,validators=[uniqueness(dbqry=dbQry)])
    choices2 = session.query(Data2.id,Data2.description).all()
    data2_id = SelectField('Select Field 2',choices=choices2,validators=[uniqueness(dbqry=dbQry)])
    description = StringField('Description',validators=[Inputrequired(),uniqueness(dbqry=dbQry)])
    submit = SubmitField('Submit Data')

# Question5: Or here? 'dbQry' will be used in the above deFinition before the variable deFinition below; How can
# this be addressed?
# dbQry = qry(Data3,'description')

我在自定义验证器的代码中提到的链接here。这可能没有正确呈现。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)