【问题标题】:Cleanest Way to Allow Empty Scheme in Django URLField在 Django URLField 中允许空方案的最简洁方法
【发布时间】:2018-10-03 15:09:41
【问题描述】:

我正在使用 Django 2.0 并尝试允许用户在 django ModelForm 中输入指向其网站的链接。我希望我的 URLField 验证 url,即使它们没有方案前缀。

我已阅读此解决方案:django urlfield http prefix。我想知道是否有一种方法可以实现这一点,而无需在 RegexValidator 中编写我自己的自定义正则表达式。重复 URLValidator 中内置的所有正则表达式逻辑似乎不是一个非常干燥的解决方案。

我想做如下的事情:

website = models.CharField(max_length=400, blank=True, null=True, validators=[URLValidator(schemes=['', 'http', 'https', 'ftp', 'ftps'])])

这显然不起作用,因为 URLValidator 的调用方法根据给定方案进行验证的方式。

    def __call__(self, value):
        # Check first if the scheme is valid
        scheme = value.split('://')[0].lower()
        if scheme not in self.schemes:
            raise ValidationError(self.message, code=self.code)

将空字符串添加到方案列表不起作用,因为以这种方式拆分 url 会返回整个 URL(因为如果用户不包含方案前缀,则用户通常不包含 ://)。

现在,我可以子类化 URLField 并覆盖整个 call 方法以更改它处理方案的方式,但 call 方法包含所有正则表达式,所以这似乎不再是 DRY而不是简单地将 URLField 正则表达式复制到我自己的 RegexValidator 中。

是否有更简洁或更“Djangonic”的方式来实现这一目标?

【问题讨论】:

    标签: django django-validation


    【解决方案1】:

    您可以在调用super() 之前将URLValidator 子类化并使用http:// 作为前缀无方案值。这避免了来自URLValidator 的任何重复代码。

    from django.core.validators import URLValidator
    
    class OptionalSchemeURLValidator(URLValidator):
        def __call__(self, value):
            if '://' not in value:
                # Validate as if it were http://
                value = 'http://' + value
            super(OptionalSchemeURLValidator, self).__call__(value)
    

    【讨论】:

    • 这对我来说很有意义。我将此代码添加到我的 models.py 字段的顶部,并将验证器添加到我的对象定义中的网站字段,如下所示:website = models.CharField(max_length=400, blank=True, null=True, validators=[OptionalSchemeURLValidator])。但是,我使用输入“www”测试了该字段并验证了它。至少, URLValidator 正则表达式需要一个点,所以似乎没有验证。我认为我如何包含代码存在一个基本问题。
    • 你需要实例化URLValidator OptionalSchemeURLValidator:validators=[OptionalSchemeURLValidator()])
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多