2010-11-22 11 views
4

私は自分のウェブサイトにある既存のURLのエイリアスを作成できるURLエイリアスアプリを構築しようとしています。Django:リクエストオブジェクトの作成/変更

私はrequest.META['PATH_INFO']は別名のデータベース・レコードと照合された場合、ミドルウェア経由でこれをやろうとしている:

try: 
    src: request.META['PATH_INFO'] 
    alias = Alias.objects.get(src=src) 
    view = get_view_for_this_path(request) 

    return view(request) 
except Alias.DoesNotExist: 
    pass 

return None 

しかし、これは正常に動作することが(少なくとも)という生命重要ですPATH_INFOが宛先パスに変更されます。

開発者がテストリクエストオブジェクト(http://djangosnippets.org/snippets/963/,http://djangosnippets.org/snippets/2231/)を作成できるようにするためのスニペットがありますが、これはテスト目的のためのものです。

もちろん、これらのスニペットは実際の環境での使用に適している可能性がありますが、Djangoのリクエスト処理についての知識はこれを評価するにはあまりにも未開発です。

+1

リダイレクトは、彼らはそれが簡単にコードを維持するために作るので良くないだけですが、また - 彼らはあなたがページごとに固有のURLを持っていることができます。おそらくあなたの検索ランキングにとっては良いでしょう。 – Evgeny

+0

ロボットがエイリアスURLに直接アクセスするのをブロックすることでこれを回避できますか? –

答えて

4

あなたが取っているアプローチの代わりに、Redirectsアプリを考えましたか?

それは目に見えないパス/ fooのエイリアス/ビューのバーを(返すように)しませんが、コメントは改行をサポートしていないようですので、それが答えとして掲載(/ fooの/へ/バー/

+0

Stevejalimの提案に感謝します。しかし、目に見えないエイリアシングは私が目指していたものでした。 リクエストに関して、私は間違いなくリクエストオブジェクトが(QueryDictsがあるので)不変であると仮定しました。 request.path、request.path_infoなどのリクエストの属性を変更することも可能です。まだ私のexpirimentalコードをテストしていませんが、終了したら回答として結果を投稿します。 –

+0

あなたが満足しているソリューションを見つけられたらうれしいですが、Izzですが、デバッグやメンテナンスだけでなく、リクエストオブジェクトのパスを変更することで、より多くの苦痛に遭うことになります。既存のDjango URLの新しいパスを設定することは可能ですか?(必要に応じて、contribアプリケーション用の新しいカスタムurlconfsを使用することは可能でしょうか?) –

1

をリダイレクトします

アドバイスありがとうございます、私はリクエスト属性を変更するのと同じ感触を持っています。 Djangoのマニュアルには、読み込み専用と考えるべき理由があるに違いありません。

私は、このミドルウェアを思い付いた:

def process_request(self, request): 
    try: 
     obj = A.objects.get(src=request.path_info.rstrip('/')) #The alias record. 
     view, args, kwargs = resolve_to_func(obj.dst + '/') #Modified http://djangosnippets.org/snippets/2262/ 
     request.path = request.path.replace(request.path_info, obj.dst) 
     request.path_info = obj.dst 
     request.META['PATH_INFO'] = obj.dst 
     request.META['ROUTED_FROM'] = obj.src 
     request.is_routed = True 

     return view(request, *args, **kwargs) 
    except A.DoesNotExist: #No alias for this path 
     request.is_routed = False 
    except TypeError: #View does not exist. 
     pass 

    return None 

しかし、リクエストの属性を変更することに対して異議を考えると、それだけでその部分をスキップするためのより良い解決策になる、とだけis_routedを追加しないだろうし、 ROUTED_TO(ルートからではなく)部品?

元のパスに依存するコードは、METAのキーを使用できます。

URLConfsを使用してこれを行うことはできません。このエイリアシングは、エンドユーザがコードベースへのアクセス権を持たないか、または書き込み方法がわからないという前提で、エンドユーザが自分のURLを設定できるようにするためです彼自身のURLConf。

ユーザが読める編集可能なファイル(たとえばXMLなど)を有効なDjango URLに変換する関数を記述することは可能ですが、データベースレコードを使用するとエイリアスをより動的に生成できます自分のエイリアス)。

1

申し訳ありませんがnecro-postですが、回答を検索しているうちにこのスレッドが見つかりました。私の解決策はもっと簡単に思える。たぶん私は新しいジャンゴの機能に依存している、またはb)落とし穴がない。

「Mediapartners-Google」という名前のボットがあり、URLパラメータがまだナイーブなスクラップからエンコードされている(または見た目によっては二重にエンコードされた)ページを要求しています。私は次のようになり、それからの私のログに404エラーています(これは、Google AdSenseののボットです)

1.2.3.4 - - [12/Nov/2012:21:23:11 -0800] "GET /article/my-slug-name%3Fpage%3D2 HTTP/1.1" 1209 404 "-" "Mediapartners-Google 

は、通常、私はちょうど壊れたボットを無視するだろうが、これは私はそれがより良い私たちの広告をターゲットにするべきだので、なだめるしたいです私たちのコンテンツを見ることができれば、より良い収入をもたらします。噂ではリダイレクトに従わないので、元のQと同じような解決策を見つけたいと思っています。私は通常のクライアントがこれらの破損したURLによってページにアクセスするのを望まないので、ユーザーエージェントを検出します。他のアプリケーションはおそらくそれをしません。

リダイレクトは通常正しい答えになることに同意します。

私の(?完了)ソリューション:

from django.http import QueryDict 
from django.core.urlresolvers import NoReverseMatch, resolve 

class MediapartnersPatch(object): 
    def process_request(self, request): 
     # short-circuit asap 
     if request.META['HTTP_USER_AGENT'] != 'Mediapartners-Google': 
      return None 

     idx = request.path.find('?') 
     if idx == -1: 
      return None 

     oldpath = request.path 
     newpath = oldpath[0:idx] 
     try: 
      url = resolve(newpath) 
     except NoReverseMatch: 
      return None 

     request.path = newpath 
     request.GET = QueryDict(oldpath[idx+1:]) 
     response = url.func(request, *url.args, **url.kwargs) 
     response['Link'] = '<%s>; rel="canonical"' % (oldpath,) 
     return response 
関連する問題