在Django URLField中允许空方案的最简洁方法

cma*_*bst 5 django django-validation

我正在使用Django 2.0并试图允许用户在django ModelForm中输入他们网站的链接.我想让我的URLField验证网址,即使它们没有方案前缀.

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

我想做类似下面的事情:

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

这显然不起作用,因为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)
Run Code Online (Sandbox Code Playgroud)

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

现在,我可以继承URLField并覆盖整个调用方法,以便改变它处理方案的方式,但是调用方法包括所有的正则表达式,所以这似乎不再仅仅是将URLField正则表达式复制到我自己的RegexValidator中.

是否有更清洁或更"Djangonic"的方式来实现这一目标?

Ala*_*air 9

您可以在调用之前为无URLValidator方向值子类化和前缀.这避免了任何重复的代码.http://super()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)
Run Code Online (Sandbox Code Playgroud)

  • 您需要实例化`URLValidator`和`OptionalSchemeURLValidator`:`validators=[OptionalSchemeURLValidator()])`。 (2认同)