首页 文章

web2py:SQLFORM URL重复验证

提问于
浏览
0

我想禁止用户能够将重复的URL提交到数据库中 .

现在我的方法是:

db.url.URL.requires=[IS_URL(error_message='URL Error'),
                     IS_NOT_IN_DB(db, 'url.URL',error_message='Dupilcated URL')]

它涵盖了"http"和没有"http"的情况 . 例如,如果www.123.com已经在数据库中,则用户无法提交http://www.123.com . 但是这种方法并不涵盖"https"的情况,即用户仍然可以提交https://www.123.com .

反正有没有阻止这种重复?

我想在调用SQLFORM() . process()之前在URL中删除“http”/“https”(如果有的话) . 这样,数据库中的URL都没有“http”/“https” . 但是在调用SQLFORM() . process()之前我不知道如何编辑用户输入 .

现在我的代码是

url_form=SQLFORM(db.url).process()

有任何想法吗?

谢谢!

2 回答

  • 1

    您可以创建自定义验证程序以在进一步处理之前去除http / https:

    import re
    db.url.URL.requires = [lambda url: (re.sub(r'http[s]?://', '', url), None),
                           IS_URL(error_message='URL Error'),
                           IS_NOT_IN_DB(db, 'url.URL',error_message='Dupilcated URL')]
    

    注意,自定义验证器返回一个元组,包括更改的URL和 NoneNone 表示没有错误) . 然后将更改的URL传递给剩余的两个验证器 .

    请注意,默认情况下, IS_URL 会将"http://"添加到任何缺少方案的URL(在这种情况下将是所有URL,因为第一个验证器会剥离方案) . 要抑制该行为,您可以执行 IS_URL(prepend_scheme=None) .

  • 1

    您可以创建一个custom validator,它将检查数据库中的http和https版本 . 这也允许格式化URL . 考虑所有小写主机名和删除网址中的关键字参数( ?a=b ) . 如果您打算这样做,请务必查看urlparse .

    以下代码未经测试,但可能为您提供足够的代码来创建自己的解决方案 .

    class scheme_independant_url_is_not_in_db:
        def __init__(self, db,error_message='Duplicate URL'):
            self.db = db
            self.e = error_message
    
        def __call__(self, value):
            # test the entered uri
            url_validator = IS_NOT_IN_DB(db,'url.URL')
            value, error = url_validator(value)
            if error: 
                return value,self.e
            # find the opposing scheme
            if value.lower().startswith('http:'):
                opposite_scheme_value =  'https:'+value[5:] 
            elif value.lower().startswith('https:')
                opposite_scheme_value =  'http:'+value[6:] 
            # error on the opposite_scheme_value in db
            value, error = url_validator(opposite_scheme_value)
            if error: 
                return value,self.error_message
            # return the original url, preserving the original scheme
            return (value, None)
    ... 
    
    db.url.URL.requires=[IS_URL(error_message='URL Error'),
                     scheme_independant_url_is_not_in_db(db)]
    

相关问题