在Django URLField中允许空方案的最干净方法 [英] Cleanest Way to Allow Empty Scheme in Django URLField

查看:130
本文介绍了在Django URLField中允许空方案的最干净方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我已阅读以下解决方案: django urlfield http前缀.我想知道是否有一种无需在RegexValidator中编写我自己的自定义regex的方法.重复内置在URLValidator中的所有正则表达式逻辑似乎不是一个非常干燥的解决方案.

我想做以下事情:

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

由于URLValidator的call方法针对给定方案进行验证的方式,这显然不起作用.

    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并覆盖整个调用方法,以更改其处理方案的方式,但是该调用方法包括所有正则表达式,因此似乎不再是DRY而不是简单地将URLField正则表达式复制到我自己的RegexValidator中.

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

解决方案

您可以在调用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)

I'm using Django 2.0 and trying to allow users to input a link to their website in a django ModelForm. I would like for my URLField to validate urls even when they have no scheme prefix.

I have read this solution: django urlfield http prefix. I'm wondering if there is a way to achieve this without writing my own custom regex in a RegexValidator. It doesn't seem like a very DRY solution to repeat all of the regex logic that is built into the URLValidator.

I want to do something like the below:

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

This obviously doesn't work because of the way the URLValidator's call method validates against the given schemes.

    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)

Adding an empty string to the schemes list doesn't work because splitting the url in this way returns the entire URL (as a user typically does not include :// if that user is not including a scheme prefix).

Now, I could subclass URLField and overwrite the entire call method in order to change the way that it handles schemes, but the call method includes all of the regex so this seems to be no more DRY than simply copying the URLField regex into my own RegexValidator.

Is there a cleaner or more "Djangonic" way to achieve this?

解决方案

You could subclass the URLValidator and prefix schemeless values with http:// before calling super(). This avoids any duplication of code from 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)

这篇关于在Django URLField中允许空方案的最干净方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆