Djangoのreverse()とは


218

時々djangoコードを読むと、いくつかのテンプレートに表示されreverse()ます。これが何であるかはよくわかりませんが、HttpResponseRedirectと一緒に使用されます。これはいつどのようにreverse()ように使用されることになっていますか?

誰かがいくつかの例を挙げて答えを出すといいですね...


26
URLパターンが与えられると、Djangoはurl()を使用して適切なビューを選択し、ページを生成します。それは、ありますurl--> view name。ただし、リダイレクトの場合と同様に、逆方向に移動してDjangoにビューの名前を付ける必要がある場合があります。Djangoは適切なURLを生成します。つまり、view name --> urlです。つまり、reverse()(これはurl関数の逆です)。ちょうどそれを呼び出すために、より透明に見えるかもしれないgenerateUrlFromViewName:それはあまりにも長い間、おそらく一般的な十分ではありませんdocs.djangoproject.com/en/dev/topics/http/urls/...
エリック・

4
@neuronet素晴らしい説明、ありがとう。この名前は、私には特に直感的でないように見えました(そして思われます)。不必要な難読化を嫌っていないのは誰ですか?
マイクげっ歯類

これは、プログラマーのコンテキストを考えると、当時プログラマーの最優先事項であったエンティティ(機能など)の1つの側面を強調する命名の典型的な例ですが、他の開発者の幅広いコンテキストでは最も有用なオプションではありません。私たちはプログラマーとしてこの罠に陥ることがよくあります。命名は発見しやすさにとって非常に重要です。さまざまなコンテキストについて立ち止まって考え、最も適切なものを選択する価値があります。
Cornel Masson

回答:


345

reverse()| Djangoのドキュメント


あなたの中でurls.pyこれを定義したとしましょう:

url(r'^foo$', some_view, name='url_name'),

テンプレートでは、このURLを次のように参照できます。

<!-- django <= 1.4 -->
<a href="{% url url_name %}">link which calls some_view</a>

<!-- django >= 1.5 or with {% load url from future %} in your template -->
<a href="{% url 'url_name' %}">link which calls some_view</a>

これは次のようにレンダリングされます:

<a href="/foo/">link which calls some_view</a>

ここで、同じようなことをしたいとしますviews.py-たとえば/foo/、他のビュー(ではない)で他のURL(ではない)を処理していてsome_view、ユーザーをリダイレクトしたい/foo/場合(多くの場合、フォームの送信が成功した場合)。

あなたはただ行うことができます:

return HttpResponseRedirect('/foo/')

しかし、将来URLを変更したい場合はどうでしょうか?あなたは更新する必要があるだろうurls.py し、あなたのコード内のそれへのすべての参照を。これはDRY(Do n't Repeat Yourself)に違反していますにしています。これは、1か所だけを編集するという全体的な考えです。

代わりに、次のように言うことができます。

from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))

これは、プロジェクトで定義されたすべてのURLを調べて、名前で定義されたURLを探しurl_name、実際のURLを返します/foo/

これは、そのname属性によってのみURLを参照することを意味します。URL自体またはURLが参照するビューを変更する場合は、1つの場所のみを編集することでこれを行うことができますurls.py


2
参考まで{{ url 'url_name' }}{% url url_name %}、Django 1.4以前である必要があります。これは、次のDjangoリリース(1.5)で変更される予定{% url 'url_name' %}です。「前方互換性」セクションまで少し下にスクロールすると、urlテンプレート
タグ

1
j_sykありがとう-1.3がリリースされて以来、@ load url from future @を実行してきましたが、それがまだデフォルトではないことを忘れていました。未経験者がつまずかないように、回答を更新します。
scytale 2012年

2
修正済み-他の人の答えのダムタイプミスを自分で編集することは完全に許容できると思うので、ジャンプするだけであれば:-)
scytale

3
このサイトで見つけることができる最も微妙な答えの1つ。
Manas Chaturvedi

1
">>>しかし、将来的にURLを変更したい場合はどうすればよいでしょうか?" .0001%の時間で役立つこれらの種類の微妙な問題とソリューションは、便利な機能のように出荷され、人々はそれをまるで 'ベストプラクティス」と混乱を残します。TBHは、将来URLを変更したときに、グローバルな検索置換を行うだけの場合です。この解決策(url_nameを使用)でも、「将来的にurl_nameを変更したい場合はどうなりますか?」という問題が発生しやすくなります。5年以上Djangoでコーディングを行っており、まだのニーズを満たしていませんurl_reverse。これらの種類の奇妙な点に対処する最善の方法は、それらの使用を拒否することです。
ネヘム2017年

10

これは古い質問ですが、これは誰かを助けるかもしれないものです。

公式ドキュメントから:

Djangoは、URLが必要なさまざまなレイヤーに一致するURL反転を実行するためのツールを提供します。テンプレート内:urlテンプレートタグを使用します。Pythonコード:reverse()関数の使用。DjangoモデルインスタンスのURLの処理に関連する上位レベルのコード:get_absolute_url()メソッド。

例えば。テンプレート内(URLタグ)

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>

例えば。Pythonコードで(reverse関数を使用)

return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

1
詳しい説明が必要な上司
giveJob 2018年

OPは、ドキュメントを読んだだけであり、単にドキュメントからコピーして貼り付けるだけでなく、説明が必要だと述べました。
RusI

8

既存の答えは これのを説明するのに素晴らしい仕事をしましたreverse() Django機能がに役立ちました。

しかし、私は私の答えはで異なる光を当てることが期待のだ理由:使用する理由reverse()テンプレートビューで他のより直接的な、間違いなくより多くのニシキヘビのアプローチの代わりには、結合、およびこの「リダイレクトの人気のためにいくつかの正当な理由どのようなものを経由して reverse() Djangoルーティングロジックの「パターン」。

他の人が述べたように、1つの重要な利点は、URLの逆構築です。ちょうどあなたが使用する方法のような{% url "profile" profile.id %}例:アプリケーションのURL設定ファイルからURLを生成しますpath('<int:profile.id>/profile', views.profile, name="profile")

しかし、OPが指摘したように、の使用reverse()は通常、の使用とも組み合わされますHttpResponseRedirect。しかし、なぜ?

これが何であるかはよくわかりませんが、HttpResponseRedirectと一緒に使用されます。このreverse()はいつどのように使用されることになっていますか?

以下を検討してくださいviews.py

from django.http import HttpResponseRedirect
from django.urls import reverse

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected = question.choice_set.get(pk=request.POST['choice'])
    except KeyError:
        # handle exception
        pass
    else:
        selected.votes += 1
        selected.save()
        return HttpResponseRedirect(reverse('polls:polls-results',
                                    args=(question.id)
        ))

そして私たちの最小限urls.py

from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('<int:question_id>/results/', views.results, name='polls-results'),
    path('<int:question_id>/vote/', views.vote, name='polls-vote')
]

ではvote()機能、私たちの内のコードelseブロックを使用していますreverseと一緒にHttpResponseRedirect以下のパターンで:

HttpResponseRedirect(reverse('polls:polls-results',
                                        args=(question.id)

これは何よりもまず、URLをハードコーディングする必要がないことを意味します(DRYの原則に準拠)。ただし、より重要なのreverse()は、引数からアンパックされた値を処理することによってURL文字列を作成するエレガントな方法を提供します(args=(question.id)URLConfigによって処理されます)。に値を含むquestion属性があるとするid5、から構成されるURL reverse()は次のようになります。

'/polls/5/results/'

通常のテンプレートとビューのバインディングコードでは、以下の抽象化を使用するHttpResponse()render()、通常は抽象化が少なくなります。1つのテンプレートを返す1つのビュー関数:

def index(request):
    return render(request, 'polls/index.html') 

しかし、リダイレクトの多くの正当なケースでは、通常、パラメーターのリストからURLを構築することに関心があります。これには、次のような場合が含まれます。

  • POSTリクエストによるHTMLフォームの送信
  • 検証後のユーザーログイン
  • JSON Webトークンを介してパスワードをリセットする

これらのほとんどは、なんらかの形式のリダイレクトと、一連のパラメータを介して構築されたURLを含みます。これがすでに役立つ回答のスレッドに追加されることを願っています!


4

関数はドライの原則をサポートします-アプリ全体でURLをハードコードしないようにします。URLは1か所で定義する必要があり、1か所のみ-URL設定です。その後、あなたは本当にその情報を参照しているだけです。

reverse()ビューへのパス、またはurl設定からのpage_nameパラメータのいずれかを指定して、ページのURLを提供するために使用します。テンプレートでを使用しても意味がない場合に使用し{% url 'my-page' %}ます。

この機能を使用できる場所はたくさんあります。私が見つけた1つの場所は、ビューでユーザーをリダイレクトするときです(多くの場合、フォームの処理が成功した後)。

return HttpResponseRedirect(reverse('thanks-we-got-your-form-page'))

テンプレートタグを記述するときにも使用できます。

私が使用しreverse()たもう1つの時期は、モデルの継承です。親モデルにListViewがありましたが、それらの親オブジェクトのいずれかから、それに関連付けられている子オブジェクトのDetailViewに移動したいと考えました。get__child_url()子の存在を識別する関数を親にアタッチし、を使用してそのDetailViewのURLを返しましたreverse()



2

既存の答えは非常に明確です。それが呼び出される理由がわからない場合に備えてreverse:URL名の入力を受け取り、実際のURLを取得します。これは、最初にURLを取得してから名前を付けるのとは逆です。


1
チュートリアル(Django Girls)からDjangoを学ぶだけです。それは急な学習曲線です。この関数の名前は恐ろしいと思います。資格なしで「予約」することは、リストや文字列を予約することを強く強く推奨します。
マイクげっ歯類

@mikerodent私はあなたに完全に同意します。その上、これらの答えのどれも、関数が逆と呼ばれる理由を説明していません。そんな悪い名前いもです。
Soham Dongargaonkar

1

reverse()は、djangoのDRY原則を順守するために使用されます。つまり、将来URLを変更した場合、reverse(urlname)を使用してそのURLを参照できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.