Django URLField与自定义方案

时间:2017-01-20 05:18:19

标签: django

Django' django.db.models.URLField使用django.core.validators.URLValidator

class URLField(CharField):
    default_validators = [validators.URLValidator()]

由于它没有指定要接受的方案,因此URLValidator默认为此设置:

schemes = ['http', 'https', 'ftp', 'ftps']

我希望我的URLField接受ssh://个网址,所以我尝试了这个:

class SSHURLField(models.URLField):
  '''URL field that accepts URLs that start with ssh:// only.'''
  default_validators = [URLValidator(schemes=['ssh'])]

但是,当我尝试使用有效的ssh://网址保存新对象时,我会被拒绝。

如果我跳过从URLField继承并直接从CharField继承,也会发生这种情况:(编辑:实际上,在重新创建数据库之后,这确实有效。我不确定为什么前者没有#&# 39;工作。)

class SSHURLField(models.CharField):
  '''URL field that accepts URLs that start with ssh:// only.'''
  default_validators = [URLValidator(schemes=['ssh'])]

  def __init__(self, *args, **kwargs):
    kwargs['max_length'] = 64
    super(SSHURLField, self).__init__(*args, **kwargs)

当我在测试中直接使用URLValidator时,它可以工作:

def test_url(url):
  try:
    URLValidator(schemes=['ssh'])(url)
    return True
  except:
    return False

>>> test_url('ssh://example.com/')
True

>>> test_url('http://example.com/')
False

1 个答案:

答案 0 :(得分:4)

正如@IainDillingham在评论中提到的,这是Django中的一个错误:覆盖子类ModelField的default_validator不一定会覆盖与该基类关联的FormField的default_validator。

对于你的例子,django.db.models.URLField,我们可以看到它的相关表格字段 [0] 是django.forms.fields.URLField [1] 。因此,此处的解决方法是为您的自定义def formfield(...)覆盖SSHURLField,以引用具有相同验证器的自定义django.forms.fields.URLField子类,如下所示:

from django.core import validators
from django.db import models
from django.forms.fields import URLField as FormURLField

class SSHURLFormField(FormURLField):
    default_validators = [validators.URLValidator(schemes=['ssh'])]

class SSHURLField(models.URLField):  
    '''URL field that accepts URLs that start with ssh:// only.'''  
    default_validators = [validators.URLValidator(schemes=['ssh'])]  

    def formfield(self, **kwargs):
        return super(SSHURLField, self).formfield(**{
            'form_class': SSHURLFormField,
        })

[0] https://github.com/django/django/blob/e17088a108e604cad23b000a83189fdd02a8a2f9/django/db/models/fields/init.py#L2275,L2293
[1] https://github.com/django/django/blob/e17088a108e604cad23b000a83189fdd02a8a2f9/django/forms/fields.py#L650