在Django URLField中允许空方案的最干净方法 [英] Cleanest Way to Allow Empty Scheme in 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屋!