1

Django URLFieldは、ユーザー入力の最後に末尾のスラッシュ ( /) を追加して、すべての URL に余分な文字を強制的に格納することを好みますが、これは誤りです。この動作を停止し、ユーザーが送信した URL を保存するにはどうすればよいですか?

4

3 に答える 3

3

https://github.com/django/django/blob/master/django/forms/fields.pyで確認to_pythonURLFieldてください。

url_fields[2] = '/'method のほぼ最後に行があることがわかりますto_python/URL の末尾に末尾のスラッシュを追加します。これを行うためのロジックは、この行の前にコメントとして表示されます。

このスラッシュは、いくつかのクエリ パラメータが指定されている場合に必要です。

この動作を回避したい場合は、カスタム クラスから拡張しURLFieldてオーバーライドする独自のフィールドを記述します。to_python

于 2013-04-23T04:37:08.530 に答える
2

特定の 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
于 2013-04-23T06:09:27.327 に答える
0

サイトに通常の 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,
        }
    }
于 2014-02-21T20:55:09.267 に答える