4

URLField を検証する前に空白を削除するにはどうすればよいですか?

「clean_[fieldname]()」を使用することは、https: //docs.djangoproject.com/en/dev/ref/forms/validation/ から文書化された方法のようですが、URLField では機能しません。django シェルで実行できる基本的なテスト ケースに減らしました。

class XXXTestModel(models.Model):
    url  = models.URLField('URL',null=True,blank=True)
    name = models.CharField(max_length=200)
class XXXTestForm(ModelForm):
    def clean_url(self):
        return self.cleaned_data['url'].strip()
    def clean_name(self):
        return self.cleaned_data['name'].strip() 
    class Meta:
        model = XXXTestModel
        fields = (
             'url',
        )

以下を使用して Django シェルからテスト済み:

>>> django.VERSION
(1, 5, 1, 'final', 0)
>>> from xxx import XXXTestForm,XXXTestModel
>>> data = dict(url=' http://www.example.com/ ',name=' example ')
>>> f=XXXTestForm(data)
>>> f.is_valid();f.errors
False
{'url': [u'Enter a valid URL.']}
>>> f.cleaned_data
{'name': example'}

スタックオーバーフローに関するこの質問には多くの重複がありますが、解決策につながる回答はありません。

4

1 に答える 1

7

ここでの問題は、そのdjango.forms.URLField仕組みです。

django.forms.Field.cleanと定義されている:

def clean(self, value):
    """
    Validates the given value and returns its "cleaned" value as an
    appropriate Python object.

    Raises ValidationError for any errors.
    """
    value = self.to_python(value)
    self.validate(value)
    self.run_validators(value)
    return value

to_python検証の前に実行されることに注意してください。これが問題です -django.forms.URLFieldあなたが与えている値を理解できないので、それが生成する値はdjango.forms.URLField(つまりdjango.core.validators.URLValidator) の一部として既に定義されているバリデーターのセットに失敗します。

失敗する理由は、django が URL を「正規化」しようとするためです。これには、必要に応じて追加することなどが含まれ"http://"ます。あなたの例のURLが与えられると" http://www.example.com "、djangoはurlparse.urlsplitURLの「部分」を取得するために使用します。ただし、先頭のスペースはそれを台無しにし、値全体が の一部になりpathます。そのため、django は noschemeを検出し、URL を として再構成します"http:// http://www.example.com "。これは に渡されdjango.core.validators.URLValidatorますが、これは明らかに失敗します。

これを避けるにはURLField、フォーム用に独自のものを定義する必要があります

from django import forms

class StrippedURLField(forms.URLField):
    def to_python(self, value):
        return super(StrippedURLField, self).to_python(value and value.strip())

これを使用すると、プロセスがすべて期待どおりに進むことが保証され、clean_urlメソッドは必要ありません。(注:clean_*可能な場合は使用する必要がありますが、ここでは使用しません)

class XXXTestForm(forms.ModelForm):
    url = StrippedURLField(blank=True, null=True)
于 2013-11-15T02:24:43.687 に答える