【发布时间】:2018-11-25 17:14:00
【问题描述】:
在我的 Django REST Framework 项目中,我有一个模型类用于保存 Django 应用程序将在后台任务中抓取的服务:
class Service(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=250)
root_url =URLField(unique=True)
早些时候,我在本地机器上运行了这些服务和 Django 应用程序。现在我将服务和 Django 应用程序都容器化,并让它们在 Docker 上运行。
所以现在我在添加 dockerized 服务时遇到了问题,因为它的根 URL:http://sensor-service:8080/。抛出的错误是:'Enter a valid URL.'。
向我的 Django REST API 进行 POST 以及通过 Django REST 框架提供的 GUI 添加服务时都会出现此问题。
所以,基于https://stackoverflow.com/a/49262127/5433896 和http://www.django-rest-framework.org/api-guide/serializers/#field-level-validation 我尝试了以下方法。注意:最重要的行是第 5 行:允许主机名后面不跟域和/或 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)
serializers.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
但是,错误'Enter a valid URL.' 仍然被抛出。有人看到我的方法有问题吗?或者有没有人——最坏的情况,但仍然可以接受——知道如何在这个字段上完全关闭 URLValidation?
【问题讨论】:
标签: python django django-rest-framework