Django REST Framework验证错误:“输入有效的URL”。 [英] Django REST Framework validation error: 'Enter a valid URL.'
问题描述
在我的Django REST Framework项目中,我有一个模型类来保存Django应用程序将在后台任务中爬网的服务:
In my Django REST Framework project, I have a model class for saving services that the Django app will crawl in a background task:
class Service(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=250)
root_url =URLField(unique=True)
以前,我在本地计算机上同时运行了这些服务和Django应用程序。现在,我将服务和Django应用程序都进行了容器化,并使其在Docker上运行。
Earlier on, I had both these services and the Django application running on my local machine. Now I containerized both the services and the Django application and have them running on Docker.
因此,现在我在添加dockerized服务时遇到了问题,因为它的根URL: http:// sensor-service:8080 /
。引发的错误是:'输入有效的URL。'
。
So now I have a problem adding a dockerized service, because of its root URL: http://sensor-service:8080/
. The error that is thrown is: 'Enter a valid URL.'
.
出现问题在对我的Django REST API进行POST时,以及通过Django REST Framework提供的GUI添加服务时。
The problem occurs both when making a POST to my Django REST API, and when adding the Service via the GUI that the Django REST Framework provides.
因此,基于https://stackoverflow.com/a/49262127/5433896 和 http://www.django-rest-framework.org/api-guide/serializers/#field-level-validation 我尝试了以下方法。注意:最重要的一行是第5行:允许主机名后面没有域和/或TLD。
So, based on https://stackoverflow.com/a/49262127/5433896 and http://www.django-rest-framework.org/api-guide/serializers/#field-level-validation I tried the following. Note: the most important line is line 5: allowing a hostname not followed by a domain and/or TLD.
models.py:
class DockerServiceDNSUrlsCompatibleURLValidator(URLValidator):
def __init__(self, schemes=None, **kwargs):
self.host_re = '(' + self.hostname_re + self.domain_re + self.tld_re \
+ '|localhost|' \
+ self.hostname_re + ')' # <=== added: "hostname not followed by a domain and/or TLD is acceptable"
self.regex = _lazy_re_compile(r'^(?:[a-z0-9\.\-\+]*)://' # scheme is validated separately
r'(?:\S+(?::\S*)?@)?' # user:pass authentication
r'(?:' + self.ipv4_re + '|' + self.ipv6_re + '|' + self.host_re + ')'
r'(?::\d{2,5})?' # port
r'(?:[/?#][^\s]*)?' # resource path
r'\Z',
re.IGNORECASE)
super().__init__(schemes, **kwargs)
class DjangoServiceDNSUrlsCompatibleFormURLField(forms.fields.URLField):
default_validators = [DockerServiceDNSUrlsCompatibleURLValidator()]
class DjangoServiceDNSUrlsCompatibleURLField(models.URLField):
default_validators = [DockerServiceDNSUrlsCompatibleURLValidator()]
def formfield(self, **kwargs):
return super(DjangoServiceDNSUrlsCompatibleURLField, self).formfield(**{
'form_class': DjangoServiceDNSUrlsCompatibleFormURLField,
})
class Service(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=250)
root_url = DjangoServiceDNSUrlsCompatibleURLField(unique=True)
序列化器。 py:
class ServiceSerializer(serializers.HyperlinkedModelSerializer):
validators = [DockerServiceDNSUrlsCompatibleURLValidator()]
def validate_root_url(self, value):
DockerServiceDNSUrlsCompatibleURLValidator(value) # will throw validation exception if value isn't OK.
return value
但是,错误'输入有效的URL 。'
仍然被抛出。有人看到我的方法有问题吗?还是有人-最坏的情况但仍然可以接受-知道我该如何完全关闭此字段上的URLValidation?
However, the error 'Enter a valid URL.'
is still thrown. Does anyone see a problem in my approach? Or does anyone - worst case, but still acceptable - know how I can turn off the URLValidation entirely on this field instead?
推荐答案
如果您有自己的正则表达式,为什么不只使用models.CharField而不是URLField?像这样:
If you have your own regex, why not just use a models.CharField instead of URLField? Like:
models.py
phone_regex = RegexValidator(
regex=r'^\+?(?:\(?[0-9]\)?\x20?){4,14}[0-9]$',
message="Error....")
class FooModel(models.Model):
phone = models.CharField("Phone Number", validators=[
phone_regex], max_length=26, blank=True, null=True)
BTW,自定义URLValidator接受不带'http / https'的url,我在下面使用
BTW, to customize URLValidator accept urls without 'http/https' I use below
models.py
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)
class FooModel(models.Model):
website = models.CharField(max_length=200, validators=[OptionalSchemeURLValidator()])
这不会更改上传的值,只需通过验证即可。
我在DRF上尝试过,它有效。
This doesn't change the uploaded value, just make the validation pass. I tried on my DRF, it works.
请参考 Alasdair的答案,谢谢Alasdair
refer to Alasdair's answer, thanks Alasdair
这篇关于Django REST Framework验证错误:“输入有效的URL”。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!