3

GET の一部としてクエリ文字列を含む URL を受け取ることができる Django セットアップに取り組んでいます。クエリ文字列で提供されたデータを処理し、そのデータに合わせて調整されているが URL にクエリ文字列が含まれていないページを返すことができるようにしたいと考えています。

通常は を使用reverse()しますが、この場合の適用方法がわかりません。状況の詳細は次のとおりです。

URL の例: .../test/123/?list_options=1&list_options=2&list_options=3

urls.py

urlpatterns = patterns('', 
    url(r'test/(P<testrun_id>\d+)/'), views.testrun, name='testrun')
    )

ビュー.py

def testrun(request, testrun_id):
    if 'list_options' in request.GET.keys():
        lopt = request.GET.getlist('list_options')
        :
        :
        [process lopt list] 
        :
        :

    :
    :
    [other processing]
    :
    :

    context = { ...stuff... }
    return render(request, 'test_tracker/testview.html', context)

URL の例が処理されると、Django は必要なページを返しますが、URL の末尾にはクエリ文字列が含まれています。不要なクエリ文字列を削除する標準的な方法は、testrun 関数を で返すことreturn HttpResponseRedirect(reverse('testrun', args=(testrun_id,)))です。ただし、ここでそれを行うと、testrun関数を介して無限ループが発生します。さらに、元のリクエストにあった list_options データが URL から削除されているため、リダイレクト後も利用できるかどうかはわかりません。

これを回避するにはどうすればよいですか? 無限再帰を避けるために、list_options 変数の解析を別の関数に移動することは理にかなっていることがわかりますが、そのようにすると、リクエストから list_options データが失われるのではないかと心配しています。URL の末尾からクエリ文字列を同時に削除し、必要なページを 1 か所に返すためのきちんとした方法はありますか?

編集:「なぜこれをやりたいのですか?」という質問がいくつかあったため、少し余分な背景を説明します。クエリ。

私がデザインしている Web サイトは、私が取り組んでいるソフトウェアのさまざまなテストの結果を報告することです。この特定のページは、1 つのテストの結果を報告するためのもので、多くの場合、より大きなテスト リストからリンクします。

list_options配列は、先ほど取得したリスト内の他のテストを指定する方法です。これにより、ドロップダウン メニューに他の関連するテストを入力して、それらを簡単に切り替えることができます。

そのため、15 ~ 20 個の異なる値を簡単に渡して巨大な URL を作成することになる可能性がありますが、これは避けたいと思います。このページは、URL で他のテストを提案しない場合、問題のメニューを埋めるための他のテストのデフォルト セットを持つように設計されているため、list_options. ユーザーが直接ページに戻りたい場合、リスト内の他のテストは気にしないので、その情報が利用できなくても問題ありません。

4

1 に答える 1

3

最初に一言注意。これは、さまざまな理由から、おそらく良い考えではありません。

  • ブックマーク.../link?q=bar&order=fooいくつかの検索結果をフィルタリングし、結果を特定の順序で並べ替えると想像してください。クエリ文字列を自動的に削除すると、ユーザーが特定の検索クエリをブックマークすることを効果的に禁止できます。
  • テスト。自動化を追加するときはいつでも、想像もしなかった方法で問題が発生する可能性があり、おそらくそうなるでしょう。広く使用されているため、エラーが発生しにくいため、単純で効果的なアプローチに固執することをお勧めします。以下に例を示します。
  • メンテナンス。これは標準的な動作モデルではないため、将来の開発者はまず何が起こっているのかを理解する必要があるため、メンテナンスが難しくなります。

それでもこれを達成したい場合、最も簡単な方法の 1 つはセッションを使用することです。クエリ文字列がある場合は、その内容をセッションに保存し、後でクエリ文字列がないときにそれを取得するという考え方です。例えば:

def testrun(request, testrun_id):
    # save the get data
    if request.META['QUERY_STRING']:
        request.session['testrun_get'] = request.GET
        # the following will not have querystring hence no infinite loop
        return HttpResponseRedirect(reverse('testrun', args=(testrun_id,)))

    # there is no querystring so retreive it from session
    # however someone could visit the url without the querystring
    # without visiting the querystring version first hence
    # you have to test for it
    get_data = request.session.get('testrun_get', None)
    if get_data:
        if 'list_options' in get_data.keys():
            ...
    else:
        # do some default option
        ...

    context = { ...stuff... }
    return render(request, 'test_tracker/testview.html', context)

それは機能するはずですが、簡単に壊れてしまう可能性があり、簡単に修正する方法はありません。これは、上から 2 番目の箇条書きを示しているはずです。たとえば、ユーザーが 2 つの検索クエリを並べて比較したいとします。そのため、同じブラウザの別のタブにアクセスしようとし.../link?q=bar&order=fooます。`.../link?q=cat&order=dog各ページで正しい結果が表示されるため、これまでのところ良好ですが、ユーザーが最初に開いたタブを更新しようとするとすぐに、2 番目のタブから結果が取得されます。これは、現在セッションに保存されているものであり、ブラウザには両方のタブに 1 つのセッション トークン。

セッションを使用せずに目的を達成するための他の方法が見つかったとしても、HTTP はステートレスであるため、サーバーに状態を保存する必要があるため、同様の問題が発生すると思います。

実際には、機能の多くを壊さずにこれを行う方法があります - サーバー側ではなくクライアントに状態を保存します。したがって、クエリ文字列のない URL を取得し、そのページに表示する必要があるものについて、javascript に API をクエリさせます。ただし、それでは、ある種の API を作成し、質問の範囲に正確に収まらない JavaScript を使用する必要があります。したがって、きれいに行うことは可能ですが、それには Django を使用するだけではありません。

于 2013-08-08T18:27:37.197 に答える