django1.11自定义身份验证后端问题-返回以/ user / xxx开头的未知URL?

时间:2019-03-23 16:30:21

标签: django

我尝试使用Django 1.11中的自定义身份验证后端来构建功能(使用用户的电子邮件登录,而不是使用用户名的常规登录。并且用户名和useremail都保存在数据库的同一用户对象中)。

使用以下代码,我可以成功使用用户名(我以HTML表单的用户名空白输入正确的用户名值)和密码作为一对登录。但是,当我使用HTML表单输入中的电子邮件值时,则会在后台调试窗口中弹出错误,如下所示:

  

错误“未找到:/ user / login /;
  “ POST /用户/登录/ HTTP / 1.1” 404“

我很好奇,因为整个urls.py和users.views.py根本没有“用户/登录”。它是怎么来的?

在寻求帮助之前,我先查看了Django官方doc(版本1.11)和堆栈溢出中的其他建议性注释,但仍对此没有适当的答案。

希望你们能救我出来并提出您的想法。

顺便说一句,我还检查了1.11 Django Docs,它说 “

Do not forget to test for the is_active attribute of the user in your own backend permission methods.

Changed in Django 1.10:
In older versions, the ModelBackend allowed inactive users to authenticate.

因此,我曾经尝试根据“ is_acitve”检查来解决此错误,但是不幸的是,我还没有解决它。

-更新:在MySQL数据库中,我注意到当前用户对象具有字段

(is_staff =1; is_active=1)

但是我不知道如何使用信息来解决我当前的问题。

我在Pycharm IDE,Django1.11,py 3.6,mysql5.7(作为用于保存用户表的数据库)中将其用完

-重要更新

:最初我的测试浏览器是google chrome,采用了以下Ruddra的更正建议后,新代码可以在浏览器中成功解决此问题(MS Edge和firefox) ,但仍然不在Google Chrome中。所以现在我更喜欢将此问题归类为“

Django 1.11自定义身份验证后端与chrome浏览器冲突”

在setting.py中,

    

    AUTHENTICATION_BACKENDS = (
    # 'django.contrib.auth.backends.ModelBackend',
    'django.contrib.auth.backends.ModelBackend', 
    )

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'users',
        'courses',
        'organization',
        'operation',
        'xadmin',
        'crispy_forms',
        'DjangoUeditor',
    ]

    AUTH_USER_MODEL = "users.UserProfile"

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                    'django.template.context_processors.media',
                ],
            },
        },
    ]

    

在urls.py中,


    from django.conf.urls import url, include
    from django.contrib import admin
    from django.views.generic import TemplateView
    import xadmin
    from .settings import MEDIA_ROOT 
    from django.views.static import serve 
    from users. views import user_login

    urlpatterns = [
        url(r'^xadmin/', xadmin.site.urls),
        url(r'^media/(?P.*)$', serve, {"document_root": MEDIA_ROOT}), 
        url('^$', TemplateView.as_view(template_name='index.html'), name='index'),
        url('^login/$', user_login, name='login'),
    name='upload'),
    ]

在users.views.py中,


    from django.shortcuts import render
    from django.contrib.auth import authenticate, login
    from django.contrib.auth.backends import ModelBackend
    from django.db.models import Q

    from .models import UserProfile

    class CustomBackend(ModelBackend):
        def authenticate(self, request, username=None, password=None, **kwargs):
            try:
                user = UserProfile.objects.get(Q(username=username) | Q(email=username))
                if user.check_password(password):
                    return user
            except UserProfile.DoesNotExist as e:
                return None


    def user_login(request):
        if request.method == "POST":
            user_name = request.POST.get("username", "")
            pass_word = request.POST.get("password", "")
            user = authenticate(username=user_name, password=pass_word)
            if user is not None:
                login(request, user)
                return render(request, "index.html")
            else:
                return render(request, "login.html", {"msg": "name or password erro!"})
        elif request.method == "GET":
            return render(request, "login.html", {})

在login.html中,

[

form action="/login/" method="post" id="jsLoginForm" autocomplete="off">
	input type='hidden' name='csrfmiddlewaretoken' value='mymQDzHWl2REXIfPMg2mJaLqDfaS1sD5' />
	div class="form-group marb20">
		label>your name</label>
		input name="username" id="account_l" type="text" placeholder="手机号/邮箱" />
	/div>
	div class="form-group marb8">
		label>your password</label>
		input name="password" id="password_l" type="password" placeholder="please input your password" />
	/div>
	div class="error btns login-form-tips" id="jsLoginTips">{{ msg }}</div>
	 div class="auto-box marb38">
		label><input type="checkbox" id="jsAutoLogin"> instant login </label>
		a class="fr" href="forgetpwd.html">forget your password?</a>
	 /div>
	 input class="btn btn-green" id="jsLoginBtn" type="submit" value="instant login > " />
 {% csrf_token %}
/form>

]

在理想情况下,以HTML格式输入正确的用户的电子邮件值和密码值后,也请按“登录”按钮,然后我假定我可以使用以下命令登录到index.html与要验证的用户名和密码相同。

1 个答案:

答案 0 :(得分:0)

我猜不确定这里可能出什么问题,其中一个视图受decoratorLoginRequiredMixin保护,该视图可能配置了user/login路由。

您还缺少的一件事是将CustomBackend添加到您的AUTHENTICATION_BACKENDS

AUTHENTICATION_BACKENDS = (
    'your_app.views.CustomBackend',
    'django.contrib.auth.backends.ModelBackend', 
    )

也在视图中,而不是在登录成功后呈现index.html,而是重定向到主页:

def user_login(request):
    if request.method == "POST":
        user_name = request.POST.get("username", "")
        pass_word = request.POST.get("password", "")
        user = authenticate(username=user_name, password=pass_word)
        if user is not None:
            login(request, user)
            return redirect(reverse('index'))
        else:
            return render(request, "login.html", {"msg": "name or password erro!"})
    elif request.method == "GET":
        return render(request, "login.html", {})

另外,像这样更新login_html

<form action="{% url 'login' %}" method="post" id="jsLoginForm" autocomplete="off">