I try to use the custom Authentication Backend in Django 1.11 to build the function (log-in with the user's email rather than the regular log-in with username. And both username and useremail are saved in the same user object in database).
With the following code, I can successfully login with username(I input correct username value in HTML form's username blank) and password as a pair. But in turn while I use the email value from HTML form input, It popups the Error as below in the background debug window:
error "Not Found: /user/login/ ;
"POST /user/login/ HTTP/1.1" 404 "
I am very curious because there is never "user/login" at all in my whole urls.py and users.views.py. how does it come from?
Before this inquiry for help, I look up in Django official doc(version 1.11) and other suggestive comments in our stack overflow, but it still has no proper answer with this.
Hope your guys save me out and give your ideas.
Btw, I also check on 1.11 Django Docs, it said that "
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.
So I ever tried to solve this error according to the "is_acitve" check, but unfortunately, I don't' get it fixed yet.
-- Update: in MySQL db, I notice the current user object have fields
(is_staff =1; is_active=1)
but I don't get how to use the info to solve my current problem.
I run it out in Pycharm IDE, Django1.11, py 3.6, mysql5.7 (as DB to save the user table)
--Important Update
: originally my testing browser is google chrome, after adopting the following Ruddra's correcting suggestion, new code can solve the issue successfully in browsers ( MS edge and firefox), but still not in google chrome. So now I prefer to classify this issue to "Django 1.11 custom authentication backends have a conflict with chrome browser"
in 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', ], }, }, ]
in 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'), ]
in 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", {})
in 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>
]
In the ideal situation, after I input the correct user's email value and password value in HTML form, pressing 'login" button as well, then I assume to see I can log in to the index.html as I log in with the same user's name and user password as a pair to authenticate.