web-dev-qa-db-ja.com

DjangoのバリデーターでURLが存在するかどうかを確認するにはどうすればよいですか?

チェックインしたいDjango URLが存在するかどうか、存在する場合は画面に何かを表示したい、つまり:

if URL_THAT_POINTS_TO_SOME_PDF exists 
     SHOW_SOMETHING
19

編集:これはDjango 1.5以上のバージョンでは無効になっていることに注意してください

オブジェクトだけではなく、ファイルが実際に存在するかどうかを確認したいと思います(これは単純なifステートメントです)

まず、Djangoのソースコードを常に確認することをお勧めします。 いくつかの優れたコードを見つける 使用できるからです:)

テンプレート内でこれを実行したいと思います。 URLを検証するための組み込みのテンプレートタグはありませんが、基本的にはテンプレートタグ内でそのURLValidatorクラスを使用してテストできます。単に:

from Django.core.validators import URLValidator
from Django.core.exceptions import ValidationError

validate = URLValidator(verify_exists=True)
try:
    validate('http://www.somelink.com/to/my.pdf')
except ValidationError, e:
    print e

URLValidatorクラスは、リンクを開くことができない場合、ValidationErrorを吐き出します。それは使用しています urllib2実際にリクエストを開いて、基本的な正規表現チェックを使用するだけではありません(ただし、それも実行します)。

これをカスタムテンプレートタグに入れることができます。これは、Djangoドキュメントで作成する方法を見つけることができます。

それがあなたのスタートであることを願っています。

48
Bartek

verify_existsパラメータからDjango.core.validators.URLValidatorに基づくものはすべて、Django 1.5 — ドキュメント はこれについて何も述べていませんが、- ソースコード 1.4(最新の安定バージョン)でそのメカニズムを使用すると、DeprecationWarningにつながることがわかります( 開発バージョンでは完全に削除されています =):

if self.verify_exists:
    import warnings
    warnings.warn(
        "The URLField verify_exists argument has intractable security "
        "and performance issues. Accordingly, it has been deprecated.",
        DeprecationWarning
        )

このメソッドには、HEADリクエストを使用してURLをチェックするという奇妙な癖もあります。帯域幅効率は確かですが、一部のサイト(Amazonなど)はエラーで応答します(HEAD、ここで同等のGETは問題ありませんでした)、これは バリデーターからの偽陰性の結果 につながります。

また、テンプレートでurllib2を使用して何もしないことをお勧めします(2年間で大幅に変更されました)。これは、実行が長くなる可能性のある操作をトリガーする要求/応答サイクルの完全に間違った部分です。 URLが存在するが、DNSの問題により、urllib2がそれを解決するのに10秒かかる場合。バム!ページの読み込み時に10秒余分にかかります。

このような非同期の可能性のある長時間実行タスクを作成する(したがってページの読み込みをブロックしない)ための現在のベストプラクティスは、Django-celeryを使用することです。 基本的なチュートリアルpycurlを使用してWebサイトをチェックする方法、または Simon Willisonがセロリタスクを実装した方法 (スライド32-41) Lanyrdの同様の目的。

6
supervacuo

問題

from Django.core.validators import URLValidatorは、www.google.roが無効であることを示しています。私の見解ではどちらが間違っています。または少なくとも十分ではありません。

それを解決する方法は?

手がかりは、models.URLFieldのソースコードを調べることです。バリデーターとしてforms.FormFieldを使用していることがわかります。上からURLValidator以上のことをします

解決策

http://www.google.comwww.google.roのようなurlを検証したい場合は、次のようにします。

django.formsからインポートURLField

def validate_url(url):
    url_form_field = URLField()
    try:
        url = url_form_field.clean(url)
    except ValidationError:
        return False
    return True

これは便利だと思いました。多分それは他の誰かを助けます。

2
Mihai Zamfir

追加が必要でした:

django.core.exceptionsからimportValidationError

それが私のために働くために。ただ言う; 0)

2
ropz
_from Django.core.validators import URLValidator
from Django.core.exceptions import ValidationError

validate = URLValidator(verify_exists=True)    
value = request.GET.get('url', None)

if value:        
    try:
        validate(value)
    except ValidationError, e:
        print e
_

validate(value)は、URLの前に_http://_のようなスキーマがない場合は失敗します。それは仕様によるものなのだろうか。

1
Mohammad Ali

私はここで答えを見ていません。それは他の誰かに役立つかもしれません。

from Django import forms
f = forms.URLField()
try:
    f.clean(http://example.com)
    print "valid url"
except:
    print "invalid url"
0
Jishad AV

参照: http://www.agmweb.ca/2009-04-19-Django-urlpatterns---its-more-than-just-urls/

Django 1.10で私は今使用します:

from Django.core.urlresolvers import RegexURLResolver, Resolver404

if 'next' in request.GET.keys():
    n = request.GET["next"].strip('/') + "/"
    resolver = RegexURLResolver(r'', urls)
    try:
        callback, callback_args, callback_kwargs = resolver.resolve(n)
        return HttpResponseRedirect(str(request.GET["next"]))
    except Resolver404:
        raise PermissionDenied("This page is not available")
0