Django URLField喜欢在用户输入的末尾添加一个尾部斜杠(/
),强制所有的URL都与额外的字符一起存储,这是错误的。如何停止此行为并保存用户提交的URL?
答案 0 :(得分:3)
在https://github.com/django/django/blob/master/django/forms/fields.py检查to_python
的{{1}}。
您可以看到它几乎在方法URLField
的末尾有一行url_fields[2] = '/'
。它在url的末尾附加一个尾部斜杠to_python
。您可以在此行之前看到将此作为注释的逻辑。
如果给出一些查询参数,则必须使用此斜杠。
如果您想避免此行为,请编写自己的字段,该字段从/
延伸并覆盖自定义类中的URLField
。
答案 1 :(得分:2)
我也一直在努力解决这个问题,因为它会导致某些网址出现问题。例如,http://www.nasa.gov/mission_pages/kepler/news/kepler-62-kepler-69.html/失败,但它没有斜杠。
为了扩展akshar的答案,我们解释了执行此操作的方法here。例如,在我的models.py文件中定义它并在我的模型中设置url = NoSlashURLField()
而不是models.URLField()
会删除斜杠:
try:
from urllib.parse import urlsplit, urlunsplit
except ImportError: # Python 2
from urlparse import urlsplit, urlunsplit
class NoSlashURLField(models.URLField):
description = "Remove the goddamn slash"
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
super(NoSlashURLField, self).__init__(*args, **kwargs)
def to_python(self, value):
def split_url(url):
"""
Returns a list of url parts via ``urlparse.urlsplit`` (or raises a
``ValidationError`` exception for certain).
"""
try:
return list(urlsplit(url))
except ValueError:
# urlparse.urlsplit can raise a ValueError with some
# misformatted URLs.
raise ValidationError(self.error_messages['invalid'])
value = super(NoSlashURLField, self).to_python(value)
if value:
url_fields = split_url(value)
if not url_fields[0]:
# If no URL scheme given, assume http://
url_fields[0] = 'http'
if not url_fields[1]:
# Assume that if no domain is provided, that the path segment
# contains the domain.
url_fields[1] = url_fields[2]
url_fields[2] = ''
# Rebuild the url_fields list, since the domain segment may now
# contain the path too.
url_fields = split_url(urlunsplit(url_fields))
# if not url_fields[2]:
# # the path portion may need to be added before query params
# url_fields[2] = '/'
value = urlunsplit(url_fields)
return value
答案 2 :(得分:0)
对于那些使用通常的Django管理表单为他们的站点,并使用South进行数据库迁移的人,您可能希望使用以下方法而不是stonefury。他的方法改变了模型字段,除非你添加一些特殊代码,否则会混淆南方。以下方法仅更改了 admin 代码,使South无法保持幸福。
在您的应用中的某个位置定义此类:
class NoSlashURLFormField(forms.URLField):
def to_python(self, value):
def split_url(url):
"""
Returns a list of url parts via ``urlparse.urlsplit`` (or raises a
``ValidationError`` exception for certain).
"""
try:
return list(urlsplit(url))
except ValueError:
# urlparse.urlsplit can raise a ValueError with some
# misformatted URLs.
raise ValidationError(self.error_messages['invalid'])
if value:
url_fields = split_url(value)
if not url_fields[0]:
# If no URL scheme given, assume http://
url_fields[0] = 'http'
if not url_fields[1]:
# Assume that if no domain is provided, that the path segment
# contains the domain.
url_fields[1] = url_fields[2]
url_fields[2] = ''
# Rebuild the url_fields list, since the domain segment may now
# contain the path too.
url_fields = split_url(urlunsplit(url_fields))
value = urlunsplit(url_fields)
return value
然后编辑您的admin.py文件,如下所示:
from your_app.path.to.noslash import NoSlashURLFormField
from django.contrib.admin.widgets import AdminURLFieldWidget
class MyModelAdmin(admin.ModelAdmin):
...
formfield_overrides = {
models.URLField: {
'form_class': NoSlashURLFormField,
# Need to specify the AdminURLFieldWidget here because it would
# otherwise get defaulted back to URLInput.
'widget': AdminURLFieldWidget,
}
}