2010-12-18 10 views
12

'http:// localhost/entity/id /?overlay = other_id'のようなURLでdjangoアプリケーションを作成しています。 idは、特定のエンティティの主キーであり、overlayは、ディスプレイに重ねられる第2のエンティティのためのオプションのクエリパラメータです。ユーザーは、オーバーレイを介してオブジェクトを表示するときにエンティティを更新することができます。/update/idにPOSTすると、/ entity/idにリダイレクトしたいのですが、リダイレクト時にクエリパラメータが失われるのを避けたいのです。Djangoは、クエリ文字列に依存するURLにreverse()を使用してリダイレクトします。

は例えば、私は私のurl.pyに、次の持っている:更新時にoverlay_idが必要な

... 
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update'), 
(r'^entity/(?P<id>.+)/$', 'view'), 
... 

ので、それはURLではなく、クエリパラメータの一部です。 djangoビューでは、POSTが成功した後にリダイレクトし、逆順()を使用してPythonコードのURLを参照しないようにしたいと考えています。一般的な考え方は次のとおりです。

return HttpResponseRedirect(
    reverse('views.view', 
    kwargs={ 
     'id': id, 
    }, 
) 
) 

しかし、逆にクエリパラメータを渡すにはどうすればよいですか。

おかげで、 クレイグ

答えて

5

は、あなただけのoverlay_idをチェックして、あなたのURLに追加することができませんか?

redirect_url = reverse(...) 
extra_params = '?overlay=%s' % overlay_id if overlay_id else '' 
full_redirect_url = '%s%s' % (redirect_url, extra_params) 
return HttpResponseRedirect(full_redirect_url) 
+0

PYあなたはとてもように逆に使用することができますうん、私は歯を磨く間にこれを実現しました。逆に、文字列を返すと宣言されていれば、これは明らかだったので、時にはPythonに型シグニチャがあることを望みます。ありがとう。 –

+0

私は通常、次の朝にシャワーでそれらのああの瞬間を取得します。 pdb(またはipdb)は、タイプシグネチャを調べる場合に役立ちます。 'import pdb;を投げてみてください。 pdb.set_trace() 'をあなたのコードに書き込んでください。 http://docs.python.org/library/pdb.html – istruble

4

クエリ文字列argsは正しく連結されているだけでエスケープする必要があります。

文字列連結でクエリ文字列を含むURLを構築することは、文字列連結によってSQLクエリを構築することと同様に悪い考えです。ユーザーが提供する(信頼できない)入力では、複雑で、不愉快で、特に危険です。残念ながら、Djangoはクエリパラメータをreverse関数に渡すのは簡単ではありません。

しかし、Python標準urllibは、望ましいクエリ文字列エンコーディング機能を提供します。

applicationで私はこのようなヘルパー関数を作成しました:

def url_with_querystring(path, **kwargs): 
    return path + '?' + urllib.urlencode(kwargs) 

次のようにその後、私はビューでそれを呼び出す:

quick_add_order_url = url_with_querystring(reverse(order_add), 
    responsible=employee.id, scheduled_for=datetime.date.today(), 
    subject='hello world!') 
# http://localhost/myapp/order/add/?responsible=5& 
#  scheduled_for=2011-03-17&subject=hello+world%21 

などの特殊文字の適切なエンコーディングに注意してください。スペースと感嘆符!

+0

クエリ文字列パラメータをURLエンコードする際の手間を省くことができます。 HTTPResponseRedirectがそれを行います。 –

+2

@Declan Shanaghy HTTPResponseRedirectは、クエリ文字列のアセンブリ機能を提供していません(djangoのドキュメント: "コンストラクタは単一の引数を取ります - リダイレクト先のパス")ので、自分で行う必要があります。しかし、単純な文字列の連結ではないと考えられる - これは、特殊文字や空白を含む値に対しては機能しません。 – geekQ

17

あなたはジャンゴのQueryDictオブジェクトを使用することができます

from django.http import QueryDict 

# from scratch 
qdict = QueryDict('',mutable=True) 

# starting with our existing query params to pass along 
qdict = request.GET.copy() 

# put in new values via regular dict 
qdict.update({'foo':'bar'}) 

# put it together 
full_url = reversed_url + '?' + qdict.urlencode() 

をそしてもちろん、あなたは前の回答に似て、それのための便利なメソッドを書くことができます。

3

自分でURL文字列を生成しないでください。あなたのURLを与えられます。

from django.core.urlresolvers import reverse 
print reverse('view_function_name', kwargs={"id":"id_value", "overlay_id": "overlay_id_value"}) 

# or to pass view function arguments as an array: 
print reverse('view_function_name', args=("id_value","overlay_id_value",)) 

あなたがnamed url patternsを使用する場合は、URL識別子からビュー機能を切り離すための偉大である:

# urls.py 
... 
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update', name="update_foo"), 
... 

使用それほどのようなリバース:

print reverse("update_foo", kwargs={"id":"id_value", "overlay_id": "overlay_id_value"}) 
+0

一重引用符と二重引用符の区別はありません_no_way_があります。 –

+0

3月27日の私の経験を除いて、あなたのコメントごとに自分の答えを編集したいのです。他の誰も確認できますか? – dbro

+0

文字列の先頭に "r"(または 'r' :)を忘れた可能性があります。これらの例ではなく、\ dのようなものを使っているところでは、 'r'の欠如は\ d(と他のもの)を特殊文字として解釈し、 。それは私が思い付くことができる最高の推測です。あなたが実際にそれを修正する前に動作しなかったステートメントを見つけることができれば、それを分析することができます。 –

関連する問題