具有自定义方案的Django URLField [英] Django URLField with custom scheme

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

问题描述

Django的 django.db.models。 URLField 使用 django.core.validators.URLValidator

Django's django.db.models.URLField uses a django.core.validators.URLValidator:

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

由于未指定方案要接受,URLValidator默认为以下设置:

Since it does not specify the schemes to accept, URLValidator defaults to this set:

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

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

I want my URLField to accept ssh:// URLs, so I tried this:

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

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

However when I try to save a new object with a valid ssh:// URL, I get rejected.

如果我跳过从URLField继承而直接从CharField继承,也会发生这种情况:(编辑:实际上,在重新创建数据库后,此方法可以正常工作。我不确定为什么前者不起作用。)

This also happens if I skip inheriting from URLField and inherit from CharField directly: (Edit: Actually this does work after I recreated my database. I'm not sure why the former doesn't work.)

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时,它会起作用:

When I use the URLValidator directly in a test, it works:

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


推荐答案

正如注释中提到的@IainDillingham一样,这是Django中的错误:重写子类ModelField的default_validator不一定覆盖与该基类关联的FormField的default_validator。

As @IainDillingham mentioned in the comments, this is a bug in Django: overriding the default_validator of a subclassed ModelField does not necessarily override the default_validator of the FormField to which that base class is associated.

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

For your example, django.db.models.URLField, we can see its associated form field[0] is django.forms.fields.URLField[1]. So the workaround here is to also override def formfield(...) for your customized SSHURLField, to reference a custom django.forms.fields.URLField subclass with the same validator, like so:

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

[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

这篇关于具有自定义方案的Django URLField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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