web-dev-qa-db-ja.com

Django認証とAjax-ログインが必要なURL

Djangoでコード化されたWebサイトに Ajax -nicenessを追加したいと思います。

私のDjangoコードでは、@login_requiredDjango.contrib.auth.decoratorsデコレータを使用して、認証が必要なビューをマークします。認証されていないユーザーがクリックしたときのデフォルトの動作は、ユーザーをリダイレクトすることです。/herをログインページに移動し、ターゲットページを渡します。

一部のサイトで見た、本当に気に入ったのは、ユーザーがログインページにリダイレクトされるのではなく、ログのみのユーザーに制限された場所につながるリンクをクリックすると、(JavaScriptを介して)ポップアップウィンドウが表示されることです。ログインまたは登録する彼/彼女。リダイレクションの部分はないので、ユーザーがウェブサイトを本当に好きではなく、登録に時間を浪費するのを嫌がっている場合、「戻る」キーを使用する必要はありません。

つまり、質問は次のとおりです。JavaScriptがonclickイベントを処理し、「ログインしてください」ポップアップを表示できるように、一部のリンクを「制限付き」として自動的にマークするタスクをどのように管理しますか?

49
kender

私も同じ問題に直面しており、他のビューと同じように認証を処理するために、Django ajaxビューをラップする単純なデコレータが欲しいです。1つ私にとって有望と思われるアプローチは、応答で特定の値を探すJavaScriptと組み合わせてそのようなデコレーターを使用することです。

ここは 最初 デコレータの改訂ドラフト:

from functools import wraps

def ajax_login_required(view_func):
    @wraps(view_func)
    def wrapper(request, *args, **kwargs):
        if request.user.is_authenticated():
            return view_func(request, *args, **kwargs)
        json = simplejson.dumps({ 'not_authenticated': True })
        return HttpResponse(json, mimetype='application/json')
    return wrapper

ビューは次のとおりです。

@ajax_login_required
def ajax_update_module(request, module_slug, action):
    # Etc ...
    return HttpResponse(json, mimetype='application/json')

そして、これがJavaScript(jQuery)です。

$.post('/restricted-url/', data, function(json) {
    if (json.not_authenticated) {
        alert('Not authorized.');  // Or something in a message DIV
        return;
    }
    // Etc ...
});

[〜#〜] edit [〜#〜]:提案されているように、functools.wrapsを使用しようとしました。私は実際にこのデコレータを作業コードで使用したことがないので、起こりうるバグに注意してください。

56
Eric Walker

ページテンプレートの可能性のように聞こえます。

  1. onClick="return popup(this, 'arg')"またはNoneとして提供するLINK_VIA(または何か)を渡すことができます。各リンクは<A HREF="link" {{LINK_VIA}}>some text</a>になります。

    • 匿名セッションの場合、LINK_VIAには値があります。
    • ログインセッションの場合、LINK_VIAはNoneです
  2. {% if %}タグの周りに<A HREF=...>ステートメントを使用できます。これは言葉のようです。

  3. For {% link_via %}を使用して独自のカスタムタグを作成できます。私はこれに精通していませんが、リンクとテキストを文字列として提供でき、タグで2種類のリンクのいずれかを生成できます。

5
S.Lott

私は同意します S.Lott

テンプレートをチェックし、ユーザーがログインしている場合は、通常どおりにリンクを配置し、そうでない場合は、次のように配置します

<a href="{{link}}" onclick="return login_popup()"> 

ユーザーがキャンセルと言った場合、login_popupはfalseを返します。

これはおそらく Jinja2 から macros ではるかに簡単に実行できます。

ユーザーがログインする必要のあるURLがテンプレートでわからない場合は、おそらくデザインを再検討する必要があります。

必要な場合は、Django urlディスパッチャーがビュー関数を見つけるために行うのと同じことを実行できると思います。
見る: Django.core.urlresolvers

ビュー関数を取得したら、@ login_requiredで装飾されているかどうかを確認できます。

これはおそらくカスタムタグで行われます。
Jinja2を使用する場合、タグは必要ありません。関数を実装して環境に公開するだけです。簡単ですが、Jinja2のAPIを少し読む必要があります)

5
hasen

これは、wrap .__ doc __、wrap .__ name__を使用したデコレータの提案バージョンです。

from functools import wraps

def ajax_login_required(function):
    def wrap(request, *args, **kwargs):
        if request.user.is_authenticated():
            return function(request, *args, **kwargs)
        json = simplejson.dumps({ 'not_authenticated': True })
        return HttpResponse(json, mimetype='application/json')  
    wrap.__doc__ = function.__doc__
    wrap.__= function.__name__
    return wrap

Eric Walker's ソリューションから構築されていますが、Django 2.0

# Standard Imports
import functools
import Django.http

def ajax_login_required(view_func):
    @functools.wraps(view_func)
    def wrapper(request, *args, **kwargs):
        if request.user.is_authenticated:
            return view_func(request, *args, **kwargs)

        return Django.http.JsonResponse('Unauthorized', status=401, safe=False)

    return wrapper
1
Warren Spencer