4

ユーザーが自分のWebサイトにある既存のURLのエイリアスを作成できるURLエイリアスアプリを作成しようとしています。

私はミドルウェアを介してこれを行おうとしています。ミドルウェアでは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リクエスト処理に関する私の知識は、これを評価するにはあまりにも開発されていません。

4

3 に答える 3

4

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

ビュー bar() を返すためにパス /foo/ に目に見えないエイリアスを作成することはありませんが、/foo/ を /bar/ にリダイレクトします。

于 2010-11-22T15:34:14.727 に答える
2

(コメントが改行やその他のマークアップをサポートしていないように見えるため、回答として投稿されました)

アドバイスありがとうございます。リクエスト属性の変更については同じ気持ちです。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_routedandの部分のみを追加する方が良い解決策ではないでしょうか?ROUTED_TO

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

URLConf を使用してこれを行うことはできません。このエイリアシングは、エンド ユーザーがコードベースにアクセスできないか、独自の URLConf の書き方を知らないという前提で、エンド ユーザーが独自の URL を構成できるようにすることを目的としているためです。

ユーザーが読み取り可能で編集可能なファイル (XML など) を有効な Django URL に変換する関数を作成することは可能ですが、データベース レコードを使用すると、エイリアス (独自のエイリアスを定義する他のオブジェクト) をより動的に生成できるようになります。

于 2010-11-24T11:04:50.197 に答える
1

ネクロ投稿して申し訳ありませんが、答えを探しているときにこのスレッドを見つけました。私の解決策はもっと簡単に思えます。たぶん、a) 新しい django 機能に依存しているか、b) 落とし穴を見逃しています。

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

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

通常、私は壊れたボットを無視するだけですが、これは私たちの広告をより適切にターゲティングする必要があるため(これはGoogle Adsenseのボットです)、より良い収益をもたらすはずです. リダイレクトに従わないという噂があるので、元の Q. 他のアプリケーションはおそらくそれを行いません。

通常、リダイレクトが正しい答えであることに同意します。

私の(完全な?)解決策:

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
于 2012-11-13T06:45:54.350 に答える