修复了用户邮箱登录的问题
This commit is contained in:
parent
639aa38f7f
commit
57c9063ea9
|
@ -1,36 +1,18 @@
|
|||
"""
|
||||
Django settings for XH_Digital_Management project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 5.0.6.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.0/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.0/ref/settings/
|
||||
"""
|
||||
import os
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
||||
SECRET_KEY = "django-insecure-m0r-(%p2^vzpb*5*4w4k8v$$h29zy=-!hul_hoj@m)-ykbr$c@" # 严格保密!
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = "django-insecure-m0r-(%p2^vzpb*5*4w4k8v$$h29zy=-!hul_hoj@m)-ykbr$c@"
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
DEBUG = True # 生产环节关闭调试!
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
"o339q23220.goho.co",
|
||||
"localhost"
|
||||
]
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
|
@ -113,15 +95,12 @@ TEMPLATES = [
|
|||
|
||||
WSGI_APPLICATION = "XH_Digital_Management.wsgi.application"
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'xh_digital_manage', # 数据库名
|
||||
'USER': 'office', # 用户名
|
||||
'PASSWORD': 'office240603..', # 密码
|
||||
'USER': 'wsc', # 用户名
|
||||
'PASSWORD': 'jsxh9512..', # 密码
|
||||
'HOST': 'bj-cdb-7qxczedm.sql.tencentcdb.com', # 地址
|
||||
'PORT': '59450', # 端口号
|
||||
'OPTIONS': {
|
||||
|
@ -131,9 +110,6 @@ DATABASES = {
|
|||
},
|
||||
}
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
|
@ -149,9 +125,6 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
},
|
||||
]
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/5.0/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = "zh-hans"
|
||||
|
||||
TIME_ZONE = "Asia/Shanghai"
|
||||
|
@ -160,18 +133,12 @@ USE_I18N = True
|
|||
|
||||
USE_TZ = True
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/5.0/howto/static-files/
|
||||
|
||||
STATIC_URL = "/static/"
|
||||
|
||||
STATICFILES_DIRS = [
|
||||
BASE_DIR / 'static',
|
||||
]
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
|
||||
LOGIN_REDIRECT_URL = '/' # 登录后重定向的URL
|
||||
|
@ -179,3 +146,10 @@ LOGOUT_REDIRECT_URL = '/' # 登出后重定向的URL
|
|||
|
||||
MEDIA_URL = '/media/'
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
'application.accounts.backends.EmailBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
]
|
||||
|
||||
REMEMBER_ME_DURATION = 1209600 # 记住我,账户登录状态持续14天
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
from django.contrib.auth.backends import ModelBackend
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class EmailBackend(ModelBackend):
|
||||
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||
try:
|
||||
user = User.objects.get(email=username)
|
||||
if user.check_password(password):
|
||||
return user
|
||||
except User.DoesNotExist:
|
||||
return None
|
|
@ -1,6 +1,25 @@
|
|||
from django import forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
|
||||
|
||||
class CustomAuthenticationForm(AuthenticationForm):
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class EmailAuthenticationForm(AuthenticationForm):
|
||||
username = forms.EmailField(label="Email", required=True)
|
||||
password = forms.CharField(label="Password", widget=forms.PasswordInput, required=True)
|
||||
|
||||
def clean(self):
|
||||
email = self.cleaned_data.get('username')
|
||||
password = self.cleaned_data.get('password')
|
||||
|
||||
if email and password:
|
||||
try:
|
||||
user = User.objects.get(email=email)
|
||||
if not user.check_password(password):
|
||||
raise forms.ValidationError('请输入一个正确的用户名和密码。注意,两者都区分大小写。')
|
||||
except User.DoesNotExist:
|
||||
raise forms.ValidationError('请输入一个正确的用户名和密码。注意,两者都区分大小写。')
|
||||
|
||||
return self.cleaned_data
|
||||
|
|
|
@ -1,64 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
{% load static %}
|
||||
|
||||
<head>
|
||||
|
||||
<title>数字化管理系统-登录</title>
|
||||
<title>星环集团-数字化管理系统-登录</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<!-- 网站图标 -->
|
||||
<link rel="icon" href="{% static 'images/favicon.svg' %}" type="image/x-icon">
|
||||
<!-- fontawesome icon -->
|
||||
<link rel="stylesheet" href="{% static 'fonts/fontawesome/css/fontawesome-all.min.css' %}">
|
||||
<!-- animation css -->
|
||||
<link rel="stylesheet" href="{% static 'plugins/animation/css/animate.min.css' %}">
|
||||
<!-- vendor css -->
|
||||
<link rel="stylesheet" href="{% static 'css/style.css' %}">
|
||||
|
||||
<script src="{% static 'js/particles.js' %}"></script>
|
||||
<style>
|
||||
#particles-js {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #41317f, #382a6d, #2f235b);
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.auth-wrapper {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="alertContainer" style="position: fixed; top: 10px; right: 10px; z-index: 9999; width: 300px;"></div>
|
||||
{% if user.is_authenticated %}
|
||||
<!-- 用户已登录时重定向到首页 -->
|
||||
<script type="text/javascript">
|
||||
window.location.href = "{% url 'index' %}";
|
||||
</script>
|
||||
{% else %}
|
||||
<!-- [ auth-signin ] start -->
|
||||
<div id="particles-js"></div>
|
||||
<div class="auth-wrapper">
|
||||
<div class="auth-content container">
|
||||
<div class="card">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-6">
|
||||
<!-- 添加Django表单处理的action和method -->
|
||||
<form method="post" action="{% url 'user_login' %}">
|
||||
{% csrf_token %}
|
||||
<div class="card-body">
|
||||
<!-- LOGO -->
|
||||
<img src="{% static 'images/logo-dark.svg' %}" alt="" class="img-fluid mb-4">
|
||||
<h4 class="mb-3 f-w-400">欢迎登录 星环集团 数字化管理系统</h4>
|
||||
<!-- 表单字段使用Django的表单变量 -->
|
||||
<div class="form-group mb-2">
|
||||
<label class="form-label" for="id_username">用户名</label>
|
||||
<input type="text" name="username" class="form-control" placeholder="请输入用户名称" id="id_username">
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<label class="form-label" for="id_password">密码</label>
|
||||
<input type="password" name="password" class="form-control" placeholder="请输入登录密码" id="id_password">
|
||||
</div>
|
||||
<div class="form-group text-start mt-2">
|
||||
<div class="checkbox checkbox-primary d-inline">
|
||||
<input type="checkbox" name="remember_me" id="checkbox-fill-a1">
|
||||
<label for="checkbox-fill-a1" class="cr">记住我</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 提交按钮 -->
|
||||
<button type="submit" class="btn btn-primary mb-4">登录</button>
|
||||
<p class="mb-2 text-muted">忘记密码? <a href="{% url 'password_reset' %}" class="f-w-400">重置密码</a></p>
|
||||
<h4 class="mb-3 f-w-400">欢迎登录 星环集团 数字化管理系统</h4>
|
||||
<div class="form-group mb-2">
|
||||
<label class="form-label" for="id_username">邮箱</label>
|
||||
<input type="email" name="username" class="form-control" placeholder="请输入邮箱" id="id_username">
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<label class="form-label" for="id_password">密码</label>
|
||||
<input type="password" name="password" class="form-control" placeholder="请输入登录密码" id="id_password">
|
||||
</div>
|
||||
<div class="form-group text-start mt-2">
|
||||
<div class="checkbox checkbox-primary d-inline">
|
||||
<input type="checkbox" name="remember_me" id="checkbox-fill-a1">
|
||||
<label for="checkbox-fill-a1" class="cr">记住我</label>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-4">登录</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -69,13 +65,138 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- [ auth-signin ] end -->
|
||||
|
||||
<!-- Required Js -->
|
||||
<script src="{% static 'js/vendor-all.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/bootstrap/js/bootstrap.min.js' %}"></script>
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
<script src="{% static 'plugins/bootstrap/js/bootstrap.min.js' %}"></script>
|
||||
<script src="{% static 'js/jquery.com_jquery-3.6.0.js' %}"></script>
|
||||
<script>
|
||||
particlesJS('particles-js', {
|
||||
"particles": {
|
||||
"number": {
|
||||
"value": 80,
|
||||
"density": {
|
||||
"enable": true,
|
||||
"value_area": 800
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"value": "#efedf8" // 粒子颜色
|
||||
},
|
||||
"shape": {
|
||||
"type": "circle",
|
||||
"stroke": {
|
||||
"width": 0,
|
||||
"color": "#000000"
|
||||
},
|
||||
"polygon": {
|
||||
"nb_sides": 5
|
||||
},
|
||||
"image": {
|
||||
"src": "img/github.svg",
|
||||
"width": 100,
|
||||
"height": 100
|
||||
}
|
||||
},
|
||||
"opacity": {
|
||||
"value": 0.5,
|
||||
"random": false,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 1,
|
||||
"opacity_min": 0.1,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"value": 3,
|
||||
"random": true,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 40,
|
||||
"size_min": 0.1,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"line_linked": {
|
||||
"enable": true,
|
||||
"distance": 150,
|
||||
"color": "#efedf8", // 粒子线条颜色
|
||||
"opacity": 0.4,
|
||||
"width": 1
|
||||
},
|
||||
"move": {
|
||||
"enable": true,
|
||||
"speed": 6,
|
||||
"direction": "none",
|
||||
"random": false,
|
||||
"straight": false,
|
||||
"out_mode": "out",
|
||||
"bounce": false,
|
||||
"attract": {
|
||||
"enable": false,
|
||||
"rotateX": 600,
|
||||
"rotateY": 1200
|
||||
}
|
||||
}
|
||||
},
|
||||
"interactivity": {
|
||||
"detect_on": "canvas",
|
||||
"events": {
|
||||
"onhover": {
|
||||
"enable": true,
|
||||
"mode": "repulse"
|
||||
},
|
||||
"onclick": {
|
||||
"enable": true,
|
||||
"mode": "push"
|
||||
},
|
||||
"resize": true
|
||||
},
|
||||
"modes": {
|
||||
"grab": {
|
||||
"distance": 400,
|
||||
"line_linked": {
|
||||
"opacity": 1
|
||||
}
|
||||
},
|
||||
"bubble": {
|
||||
"distance": 400,
|
||||
"size": 40,
|
||||
"duration": 2,
|
||||
"opacity": 8,
|
||||
"speed": 3
|
||||
},
|
||||
"repulse": {
|
||||
"distance": 200,
|
||||
"duration": 0.4
|
||||
},
|
||||
"push": {
|
||||
"particles_nb": 4
|
||||
},
|
||||
"remove": {
|
||||
"particles_nb": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"retina_detect": true
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
showAlert('danger', '{{ message }}');
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
function showAlert(type, message) {
|
||||
const alertHtml = `
|
||||
<div class="alert alert-${type} alert-dismissible fade show" role="alert">
|
||||
<strong>操作提示:</strong> ${message}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
</div>`;
|
||||
$('#alertContainer').html(alertHtml);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
|
|
|
@ -6,7 +6,7 @@ from .views import *
|
|||
|
||||
urlpatterns = [
|
||||
# 账号基本操作,登录、退出、密码重置
|
||||
path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='user_login'),
|
||||
path('login/', custom_login_view, name='user_login'),
|
||||
path('logout/', logout_view, name='user_logout'),
|
||||
path('password_reset/', include('django.contrib.auth.urls')),
|
||||
path('homepage', user_homepage_view, name='user_homepage'),
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import json
|
||||
from datetime import datetime, date
|
||||
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.db import transaction
|
||||
from django.db.models import Q, Sum
|
||||
from django.http import JsonResponse
|
||||
|
@ -10,13 +9,14 @@ from django.shortcuts import redirect, render, get_object_or_404
|
|||
|
||||
# Django组件导入
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import logout, authenticate, login
|
||||
from django.contrib.auth import logout, login, authenticate
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import Permission, User, Group
|
||||
from django.utils.timezone import now
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from application.accounts.forms import EmailAuthenticationForm
|
||||
# 本地Django应用导入
|
||||
from application.accounts.models import AccountProfile
|
||||
from application.accounts.viewmodels import UserPermissionItem
|
||||
|
@ -24,7 +24,7 @@ from application.hrm_mgnt.models import AnnualLeaveRecord
|
|||
from application.hrm_mgnt.models import EmployeeInformation
|
||||
from application.perf_mgnt.models import EmployeePerformanceTarget
|
||||
from application.pjt_mgnt.models import ProjectLedger
|
||||
from common.auth import group_required, custom_permission_required
|
||||
from common.auth import custom_permission_required
|
||||
from common.utils.page_helper import paginate_query_and_assign_numbers
|
||||
|
||||
from pypinyin import lazy_pinyin
|
||||
|
@ -77,40 +77,35 @@ def format_permissions(permissions):
|
|||
@csrf_protect
|
||||
def custom_login_view(request):
|
||||
template_name = 'accounts/login.html'
|
||||
|
||||
# 用户已登录,重定向到首页或其他页面
|
||||
if request.user.is_authenticated:
|
||||
return redirect('home') # 替换 'home' 为实际的重定向目标
|
||||
|
||||
return redirect('user_homepage')
|
||||
|
||||
if request.method == 'POST':
|
||||
form = AuthenticationForm(request, data=request.POST)
|
||||
if form.is_valid():
|
||||
username = form.cleaned_data.get('username')
|
||||
password = form.cleaned_data.get('password')
|
||||
form = EmailAuthenticationForm(data=request.POST)
|
||||
|
||||
# 邮箱登录逻辑
|
||||
if '@' in username:
|
||||
try:
|
||||
user = User.objects.get(email=username)
|
||||
if user.check_password(password):
|
||||
login(request, user)
|
||||
return redirect('home') # 替换 'home' 为实际的重定向目标
|
||||
else:
|
||||
messages.error(request, '用户名或密码错误。')
|
||||
except User.DoesNotExist:
|
||||
messages.error(request, '用户名或密码错误。')
|
||||
else:
|
||||
# 用户名登录逻辑
|
||||
user = authenticate(request, username=username, password=password)
|
||||
if user is not None and user.is_active:
|
||||
login(request, user)
|
||||
return redirect('home') # 替换 'home' 为实际的重定向目标
|
||||
if form.is_valid():
|
||||
email = form.cleaned_data.get('username')
|
||||
password = form.cleaned_data.get('password')
|
||||
remember_me = request.POST.get('remember_me')
|
||||
user = authenticate(request, username=email, password=password)
|
||||
|
||||
if user is not None:
|
||||
login(request, user)
|
||||
if remember_me:
|
||||
request.session.set_expiry(settings.REMEMBER_ME_DURATION)
|
||||
else:
|
||||
messages.error(request, '用户名或密码错误。')
|
||||
request.session.set_expiry(0)
|
||||
return redirect('user_homepage')
|
||||
|
||||
else:
|
||||
messages.error(request, '邮箱或密码错误。')
|
||||
|
||||
else:
|
||||
messages.error(request, '用户名或密码错误。')
|
||||
messages.error(request, '表单无效,请检查输入的内容。')
|
||||
return redirect('user_login')
|
||||
|
||||
else:
|
||||
form = AuthenticationForm()
|
||||
form = EmailAuthenticationForm()
|
||||
|
||||
return render(request, template_name, {'form': form})
|
||||
|
||||
|
|
|
@ -1,26 +1,4 @@
|
|||
@charset "UTF-8";
|
||||
/**======================================================================
|
||||
=========================================================================
|
||||
Template Name: Dasho Admin Template
|
||||
Author: Phoenixcoded
|
||||
File: style.css
|
||||
更多下载:Http://www.bootstrapmb.com
|
||||
=========================================================================
|
||||
=========================================================================
|
||||
== Table of Contents==
|
||||
- Generic classes
|
||||
- Margin, Padding, Font class, text align, position, floating, overflow, background class, text color, display class, boarder class
|
||||
- Theme Elements
|
||||
- Accordion, Button, tabs, typography, buttons, box shadow, Lable & Badges, Alert, Pagination, Breadcumb, Cards, Collapse,
|
||||
- Carousel, Grid, Progress, Model, tooltip, popover, Datepicker, Gridstack, lightbox, notification, Nestable, pnotify, rating,
|
||||
- Rangeslider, Slider, Syntax Highlighter, Tour, Treeview, Toolbar, Session Timeout, Session idle Timeout, offline, Animation
|
||||
- Forms
|
||||
- Forms Elements, Advance Form Control, Validation, Masking, Wizard, Picker, Select
|
||||
- Pages
|
||||
- Chat, authentication, Maintenance, Maps, Landingpage messages, task, Todo, Notes, Charts, Icons, Gallery, Editors,
|
||||
- Invoice, Full Calender, File Upload,
|
||||
=================================================================================
|
||||
=================================================================================== */
|
||||
/*
|
||||
description Of variables for build for theme layouts
|
||||
1) menu-caption-color
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue