Django URLFieldは、ユーザー入力の最後に末尾のスラッシュ ( /
) を追加して、すべての URL に余分な文字を強制的に格納することを好みますが、これは誤りです。この動作を停止し、ユーザーが送信した URL を保存するにはどうすればよいですか?
3 に答える
https://github.com/django/django/blob/master/django/forms/fields.pyで確認to_python
しURLField
てください。
url_fields[2] = '/'
method のほぼ最後に行があることがわかりますto_python
。/
URL の末尾に末尾のスラッシュを追加します。これを行うためのロジックは、この行の前にコメントとして表示されます。
このスラッシュは、いくつかのクエリ パラメータが指定されている場合に必要です。
この動作を回避したい場合は、カスタム クラスから拡張しURLField
てオーバーライドする独自のフィールドを記述します。to_python
特定の URL で問題が発生しているため、私もこれに苦労しています。たとえば、http://www.nasa.gov/mission_pages/kepler/news/kepler-62-kepler-69.html/は失敗しますが、スラッシュがなくても機能します。
アクシャーの答えを拡張するために、これを行う方法について説明します ここ. たとえば、モデルurl = NoSlashURLField()
ではなく、models.py ファイルと設定でこれを定義すると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
サイトに通常の Django 管理フォームを使用し、DB 移行に South を使用している場合は、stonefury の代わりに次の方法を使用することをお勧めします。彼の方法はモデル フィールドを変更するため、特別なコードを追加しない限り、South は混乱します。以下のメソッドは、管理コードのみを変更するため、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,
}
}