web-dev-qa-db-ja.com

Django @ login_requiredが次へリダイレクトした後

これは簡単な質問だと思います。小さな一歩が足りません。

(次のパラメーターの用語として)次の任意の数を実行したい:

[not signed in] -> profile -> login?next=/accounts/profile/ -> auth -> profile.
[not signed in] -> newsfeed -> login?next=/newsfeed/` -> auth -> newsfeed.

私が現在行っているのに対し:

[not signed in] -> profile -> login?next=/accounts/profile/ -> auth -> loggedin
[not signed in] -> newsfeed -> login?next=/newsfeed/ -> auth -> loggedin

どういうわけかnextパラメータをloginのフォームからauthに渡し、authにこのパラメータにリダイレクトさせたいと思っています。

現在、login.htmlで試しています:

<input type='text' name="next" value="{{ next }}">

ただし、これは次の値を取得していません。デバッグツールバーから次のことがわかります。

GET data
Variable    Value
u'next'     [u'/accounts/profile/']

views

def auth_view(request):
  username = request.POST.get('username', '')
  password = request.POST.get('password', '')
  user = auth.authenticate(username=username, password=password)

  if user is not None:
    auth.login(request, user)
    print request.POST
    return HttpResponseRedirect(request.POST.get('next'),'/accounts/loggedin')
  else:
    return HttpResponseRedirect('/accounts/invalid')

login.html

{% extends "base.html" %}

{% block content %}

  {% if form.errors %}
  <p class="error"> Sorry, you have entered an incorrect username or password</p>
  {% endif %}
  <form action="/accounts/auth/" method="post">{% csrf_token %}
    <label for="username">User name:</label>
    <input type="text" name="username" value="" id="username">

    <label for="password">Password:</label>
    <input type="password" name="password" value="" id="password">

    <input type='text' name="next" value="{{ request.GET.next }}">
    <input type="submit" value="login">
  </form>

{% endblock %}

settings

from Django.conf.urls import patterns, include, url

from Django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:

    url(r'^admin/', include(admin.site.urls)),
    ('^accounts/', include('userprofile.urls')),

    url(r'^accounts/login/$', 'Django_yunite.views.login'),
    url(r'^accounts/auth/$', 'Django_yunite.views.auth_view'),
    url(r'^accounts/logout/$', 'Django_yunite.views.logout'),
    url(r'^accounts/loggedin/$', 'Django_yunite.views.loggedin'),
    url(r'^accounts/invalid/$', 'Django_yunite.views.invalid_login'),

)

settings

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'Django.contrib.admin',
    'Django.contrib.auth',
    'Django.contrib.contenttypes',
    'Django.contrib.sessions',
    'Django.contrib.messages',
    'Django.contrib.staticfiles',
    'debug_toolbar',
    'userprofile',
)

MIDDLEWARE_CLASSES = (
    'Django.contrib.sessions.middleware.SessionMiddleware',
    'Django.middleware.common.CommonMiddleware',
    'Django.middleware.csrf.CsrfViewMiddleware',
    'Django.contrib.auth.middleware.AuthenticationMiddleware',
    'Django.contrib.messages.middleware.MessageMiddleware',
    'Django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'Django_yunite.urls'

WSGI_APPLICATION = 'Django_yunite.wsgi.application'

# Internationalization
# https://docs.djangoproject.com/en/1.6/topics/i18n/

LANGUAGE_CODE = 'en-ca'

TIME_ZONE = 'EST'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    ('assets', '/home/user/GitHub/venv_yunite/Django_yunite/static/'),
    )

TEMPLATE_DIRS = (
    './templates',
    '/article/templates',
)

STATIC_ROOT = "/home/user/Documents/static/"

AUTH_PROFILE_MODULE = 'userprofile.UserProfile'

印刷ステートメントは空のu'next'を示しています

10
Matt Stokes

クエリ文字列は、特別なコードを記述しなくても、暗黙的に任意のビューに渡されます。

nextキーが実際のログインフォーム(この場合、これは/accounts/login/でレンダリングされるフォーム)から/accounts/authビューに渡されることを確認するだけです。

これを行うには、設定でリクエストテンプレートコンテキストプロセッサ(Django.core.context_processors.request)が有効になっていることを確認する必要があります。これを行うには、最初にTEMPLATE_CONTEXT_PROCESSORSのデフォルト値をインポートしてから、次のようにsettings.pyにリクエストプロセッサを追加する必要があります。

from Django.conf import global_settings

TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
    "Django.core.context_processors.request",
) 

次に、次の形式で:

<form method="POST" action="/accounts/auth">
    {% csrf_token %}
    <input type="hidden" name="next" value="{{ request.GET.next }}" />
    {{ login_form }}
    <input type="submit">
</form>

さて、あなたの/accounts/authビューで:

def foo(request):
    if request.method == 'POST':
        # .. authenticate your user


        # redirect to the value of next if it is entered, otherwise
        # to /accounts/profile/
        return redirect(request.POST.get('next','/accounts/profile/'))
14
Burhan Khalid

あなたが探しているのは ログインデコレータ です。

あなたのviews.py

from Django.contrib.auth.decorators import login_required

@login_required(login_url="/accounts/login/")
def profile( request ):
   """your view code here"""
   return HttpResponse("boo ya", "text/html")

次に、urls.pyに認証URLを追加します

(r'^accounts/login/$', 'Django.contrib.auth.views.login'),

最後に:インストールされているアプリにDjango.contrib.authがあり、AuthenticationMiddlewareがインストールされていることを確認してください。

settings.py

INSTALLED_APPS = (
   -- snip --,
   'Django.contrib.auth',
   )


MIDDLEWARE_CLASSES = (
   -- snip --,
   'Django.contrib.auth.middleware.AuthenticationMiddleware',
   )

あなたのtemplates/registerration/login.html

<form method="POST" action="/accounts/login/">
   {% csrf_token %}
   <input type="hidden" name="next" value="{{ next }}" />
   {{ login_form }}
   <input type="submit">
</form>
3
Jeff Sheffield

いつか同じような状況に直面しました。これを解決するために、私は自分のデコレータを作成しました-

def validate_request_for_login(f):
    def wrap(request):
        if not request.user.is_authenticated():
            return redirect("/login?next=" + request.path)
        return f(request)
    return wrap

上記のデコレータはユーザー認証をチェックします。ユーザーが認証されていない場合は、リクエストオブジェクトからurlを渡して、ユーザーをログインページにリダイレクトします。

1
anuragal

私がやったことは次のとおりです。私には、これはちょっとしたハックの仕事のように思えます。 csrfでログインを使用するより良い方法はありますか?

views

def login(request):
  c={}
  c.update(csrf(request))
  if 'next' in request.GET:
    c['next'] = request.GET.get('next')
  return render_to_response('login.html', c)

def auth_view(request):
  username = request.POST.get('username', '')
  password = request.POST.get('password', '')
  user = auth.authenticate(username=username, password=password)

  if user is not None:
    auth.login(request, user)

    if request.POST.get('next') != '':
      return HttpResponseRedirect(request.POST.get('next'))
    else:
      return HttpResponseRedirect('/accounts/loggedin')
  else:
    return HttpResponseRedirect('/accounts/invalid')

login.html

<input type="hidden" name="next" value="{{ next }}"/>
0
Matt Stokes