Django注册/登录不指导用户?next = / my / url

时间:2017-03-02 02:40:11

标签: django authentication login django-allauth

设置

我将[django-allauth][1]用于用户帐户。

# urls.py
url(r'^login$', allauth.account.views.login, name="account_login"),
url(r'^join$', allauth.account.views.signup, name="account_signup"), 

# settings.py
LOGIN_REDIRECT_URL = '/me' 
LOGIN_URL = '/join'  # users sent here if they run into @login_required decorator
# To collect additional info if user signs up by email:
ACCOUNT_SIGNUP_FORM_CLASS = 'allauth.account.forms.WinnerSignupForm'

该自定义注册表单:

# account/forms.py
from .models import Winner, FriendCode
class WinnerSignupForm(forms.ModelForm):
    """
        This is the additional custom form to accompany the default fields email/password (and maybe username)
    """
    class Meta:
        model = Winner
        fields = ('author_display_name','signupcode',)
        widgets = {'author_display_name':forms.TextInput(attrs={
                                            'placeholder': _('Display Name'), # 'Display Name',
                                            'autofocus': 'autofocus',
                                            })
                  ,
                  'signupcode': forms.TextInput(attrs={
                                            'placeholder': _('Invite code (optional)'), 
                                            'autofocus': 'autofocus'
                                            })
                  }


    def signup(self, request, user):
        # custom code that performs some account setup for the user
        # just runs a procedure; there's no "return" at end of this block

我认为我的自定义WinnerSignupForm导致了问题,因为即使我将其停用,问题仍然存在(即,我从settings.py注释掉这一行:{{1} })

行为

0。没有ACCOUNT_SIGNUP_FORM_CLASS = 'allauth.account.forms.WinnerSignupForm'参数:

感谢?next=/some/url中的LOGIN_REDIRECT_URL,如果我访问settings.pyexample.com/join,我将会example.com/login

没关系。

1。如果我已经登录,一切都按预期工作:

A)如果我访问example.com/me, 我立即转发到https://example.com/login?next=/some/url(没有被要求登录,因为我已经登录)。 我总结说/ login视图正确地读取https://example.com/some/url参数。

B)同样,如果我访问next=/some/url,我会立即转发至https://example.com/join?next=/some/url。 我得出结论,/ join视图也正确地读取https://example.com/some/url参数。

2。如果我通过社交帐户登录或注册,一切都按预期工作

这使用next=/some/url

我注册或登录后,转发至allauth/socialaccount

但是,问题出现了:

3。但!如果我通过电子邮件登录,?next = / some / url被忽略:

A)如果我访问https://example.com/some/url,我先带到/登录页面。 如果我通过电子邮件登录,我会转发至https://example.com/login?next=/some/url 由于某些原因,https://example.com/me并未覆盖设置中的默认?next=。 (如果我通过Twitter登录,则LOGIN_REDIRECT_URL参数被正确读取,并且我被带到?next=。)

B)同样,如果我访问https://example.com/some/url,我首先会带到/ join(注册)页面,在成功通过电子邮件登录后,我被带到{{1} },即https://example.com/join?next=/some/url中定义的后备/me

在注册/登录表单中检查POST数据," next"参数没问题:LOGIN_REDIRECT_URL

更多上下文

摘自settings.py

{"next": "/some/url", "username": "myusername", "password": "..."}

django-allauth

我非常确定当我安装# allauth/account/views.py from .utils import (get_next_redirect_url, complete_signup, get_login_redirect_url, perform_login, passthrough_next_redirect_url) ... class SignupView(RedirectAuthenticatedUserMixin, CloseableSignupMixin, AjaxCapableProcessFormViewMixin, FormView): template_name = "account/signup.html" form_class = SignupForm redirect_field_name = "next" success_url = None def get_form_class(self): return get_form_class(app_settings.FORMS, 'signup', self.form_class) def get_success_url(self): # Explicitly passed ?next= URL takes precedence ret = (get_next_redirect_url(self.request, self.redirect_field_name) or self.success_url) return ret ... 开箱即用时它最初正常工作。我必须以某种方式干涉以打破这个# allauth/account/utils.py def get_next_redirect_url(request, redirect_field_name="next"): """ Returns the next URL to redirect to, if it was explicitly passed via the request. """ redirect_to = request.GET.get(redirect_field_name) if not is_safe_url(redirect_to): redirect_to = None return redirect_to def get_login_redirect_url(request, url=None, redirect_field_name="next"): redirect_url \ = (url or get_next_redirect_url(request, redirect_field_name=redirect_field_name) or get_adapter().get_login_redirect_url(request)) return redirect_url _user_display_callable = None ... 功能,虽然我不记得它最后一次工作或者发现我做了什么来搞砸了。

非常感谢任何有关故障排除的提示。

(如果相关 - 可能没有正确读取设置; [django-allauth][1]中的?next=/some/url似乎被忽略,用户必须在重置密码后登录。)

1 个答案:

答案 0 :(得分:1)

@Akshay,以下解决方案为我工作。

我在allauth/account/adapter.py子功能中向get_login_redirect_url添加了以下行。

goto = request.POST.get('next', '')
if goto:
    return goto

澄清一下,结果如下:

class DefaultAccountAdapter(object):
    # no change to stash_verified_email, unstash_verified_email, etc.

    # edit only get_login_redirect_url as follows
    def get_login_redirect_url(self, request):
        """
        Returns the default URL to redirect to after logging in.  Note
        that URLs passed explicitly (e.g. by passing along a `next`
        GET parameter) take precedence over the value returned here.
        """
        assert request.user.is_authenticated()
        url = getattr(settings, "LOGIN_REDIRECT_URLNAME", None)
        if url:
            warnings.warn("LOGIN_REDIRECT_URLNAME is deprecated, simply"
                      " use LOGIN_REDIRECT_URL with a URL name",
                      DeprecationWarning)
        else:
            url = settings.LOGIN_REDIRECT_URL
        # Added 20170301 - look again for ?next parameter, as work-around fallback
        goto = request.POST.get('next', '')
        if goto:
            return goto
            print "found next url in adapter.py"
        else:
            print "no sign of next in adapter.py"
        # end of work-around manually added bit
        return resolve_url(url)

        # leave remainder of fn untouched 
        # get_logout_redirect_url, get_email_confirmation_redirect_url, etc.

我仍然不知道我是如何打破这个功能的,所以我不会将我的答案标记为已接受/最佳答案。但是,它确实resolve我遇到的问题,所以我很高兴。希望这对其他人有用。