一、CRM框架简介
二、登录之设计表
在登录之前,我们需要用到django内置的登录验证去做,必须得使用django定义好的表结构或者我们重写表,使用一些我们需要的字段来进行验证。没有重写之前的表为USER
表,它所在的位置为:from django.contrib.auth.models import User
源码:User继承了AbstractUser表
class User(AbstractUser):
"""
Users within the Django authentication system are represented by this
model.
Username and password are required. Other fields are optional.
"""
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
源码:AbstractUser继承了AbstractBaseUser和PermissionsMixin
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
username = models.CharField(
我们只需要重写AbstractUser表,示例如下:
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager, User
class UserProfile(AbstractBaseUser, PermissionsMixin):
username = models.EmailField(
max_length=255,
unique=True,
)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin site.'),
)
is_admin = models.BooleanField(default=False)
name = models.CharField('名字', max_length=32)
department = models.ForeignKey('Department', default=None, blank=True, null=True)
mobile = models.CharField('手机', max_length=32, default=None, blank=True, null=True)
memo = models.TextField('备注', blank=True, null=True, default=None)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'username' #定义使用的账户字段
REQUIRED_FIELDS = ['name']
class Meta:
verbose_name = '账户信息'
verbose_name_plural = "账户信息"
def get_full_name(self):
# The user is identified by their email address
return self.name
def get_short_name(self):
# The user is identified by their email address
return self.username
def __str__(self): # __unicode__ on Python 2
return self.username
def has_perm(self, perm, obj=None):
# "Does the user have a specific permission?"
# Simplest possible answer: Yes, always
if self.is_active and self.is_superuser:
return True
return _user_has_perm(self, perm, obj)
def has_perms(self, perm_list, obj=None):
# "Does the user have a specific permission?"
# Simplest possible answer: Yes, always
for perm in perm_list:
if not self.has_perm(perm, obj):
return False
return True
def has_module_perms(self, app_label):
# "Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
if self.is_active and self.is_superuser:
return True
return _user_has_module_perms(self, app_label)
当需要这张表生效时,需要在settings.py
中加入AUTH_USER_MODEL = 'crm.UserProfile'
三、登录视图函数和路由
urls.py
from django.conf.urls import url,include
from django.contrib import admin
from crm import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login,name='login'),
url(r'^register/', views.register,name='register'),
url(r'^index/', views.index,name='index'),
url(r'^logout/', views.logout,name='logout'),
url(r'^change_pwd/', views.change_pwd,name='change_pwd'),
url(r'^crm/', include('crm.urls')),
]
Model == 强大的数据库操作,弱小的数据验证
Form ==强大的数据验证
ModelForm ==二者结合,强大的数据验证,适中的数据库操作。在ModelForm是能够封装一个model对象
froms.py
from django import forms
from crm import models
from django.core.exceptions import ValidationError
# 注册form
class RegForm(forms.ModelForm):
password = forms.CharField( #重写models中定义的字段
label='密码',
widget=forms.widgets.PasswordInput(attrs={'placeholder': '请输入密码'}),
min_length=6,
error_messages={'required': '密码不能为空', 'min_length': '最小长度为6'}
)
re_password = forms.CharField( #新定义的字段
label='确认密码',
widget=forms.widgets.PasswordInput(attrs={'placeholder': '请再次确认密码'}),
min_length=6,
error_messages={'required': '密码不能为空', 'min_length': '最小长度为6'}
)
class Meta:
model = models.UserProfile
# fields = '__all__' # 所有字段
fields = ['username', 'password', 're_password', 'name', 'department'] # 指定字段
# exclude = [''] #排除的字段
widgets = { #定义插件,加入属性提示信息
'username': forms.widgets.EmailInput(attrs={'placeholder': '请输入用户名'}),
'name': forms.widgets.TextInput(attrs={'placeholder': '请输入姓名'}),
}
labels = { #显示名称
'username': '用户名',
'password': '密码',
'name': '姓名',
'department': '部门',
}
error_messages = {
'username': {
'required': '账号不能为空',
},
'name': {
'required': '姓名不能为空',
}
}
#遍历所有字段
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for filed in self.fields.values():
filed.widget.attrs.update({'class': 'form-control'})
#对clean_data的数据先进行一次验证
def clean(self):
pwd = self.cleaned_data.get('password')
re_pwd = self.cleaned_data.get('re_password')
if pwd == re_pwd:
return self.cleaned_data
self.add_error('re_password', '两次密码不一致')
raise ValidationError('两次密码不一致')
views.py
from django.shortcuts import render, HttpResponse, reverse, redirect
from django.contrib import auth
from django.contrib.auth.decorators import login_required #登录校验
from .models import UserProfile #用户表
from crm.forms import RegForm
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
print(username, password)
ok = auth.authenticate(username=username, password=password)
#Django提供的auth方法去数据库中验证用户
if ok:
auth.login(request, ok)
return redirect(reverse('customer'))
return render(request, 'login.html')
def register(request):
form_obj = RegForm() #实例化字段
if request.method == "POST":
form_obj = RegForm(request.POST)
if form_obj.is_valid():
print("校验成功")
form_obj.cleaned_data.pop('re_password') # 剔除重复的密码
UserProfile.objects.create_user(**form_obj.cleaned_data)
return redirect(reverse('login'))
return render(request, 'register.html', context={"form_obj": form_obj})
@login_required
def index(request):
return render(request, 'index.html')
#注销登录
def logout(request):
auth.logout(request)
return redirect(reverse('login'))
#改密
def change_pwd(request):
error = ''
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
new_password = request.POST.get('new_password')
re_new_password = request.POST.get('re_new_password')
ok = auth.authenticate(username=username, password=password)
print(request)
if ok:
auth.login(request, ok)
print("原账户密码正确")
if new_password:
print("密码不是空")
if new_password == re_new_password:
print("两次密码一致")
request.user.set_password(new_password)
request.user.save()
return redirect(reverse('login'))
else:
error = "两次密码不一致"
else:
error = "密码不能为空"
else:
error = "原账户或密码不正确"
return render(request, 'change_pwd.html', context={"error": error})
四、前端代码实现
1.配置settings.py
#当前端有时间显示时,会按照以下格式进行显示
DATETIME_FORMAT = 'Y-m-d H:i:s'
DATE_FORMAT = 'Y-m-d'
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static')
]
AUTH_USER_MODEL = 'crm.UserProfile' #生效的账户表
LOGIN_URL = '/login/' # 这里配置成你项目登录页面的路由
2.导入静态文件
bootstrap框架和jquey框架还有小图标框架等
前端框架 https://www.bootcdn.cn/
小图标框架 http://fontawesome.dashgame.com/
3.寻找模板
寻找合适的登录或者注册界面框架,提取需要代码和配置文件
4 login.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'css/reset.css' %}">
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<div id="particles-js">
<div class="login">
<div class="login-top">
登录
</div>
<div class="login-center clearfix">
<div class="login-center-img"><img src="{% static 'imgs/name.png'%}"></div>
<form action="" method="post">
{% csrf_token %}
<div class="login-center-input">
<input type="text" name="username" value="admin" placeholder="请输入您的用户名" onfocus="this.placeholder=''"
onblur="this.placeholder='请输入您的用户名'">
<div class="login-center-input-text">用户名</div>
</div>
</div>
<div class="login-center clearfix">
<div class="login-center-img"><img src="{% static 'imgs/password.png'%}"></div>
<div class="login-center-input">
<input type="password" name="password" value="" placeholder="请输入您的密码" onfocus="this.placeholder=''"
onblur="this.placeholder='请输入您的密码'">
<div class="login-center-input-text">密码</div>
</div>
</div>
<div style="text-align: center">
<button class="login-button">登录</button>
</div>
<div style="text-align: right; margin-top:50px;margin-right:50px;font-size:18px;">
<a href="{% url 'change_pwd'%}" style="margin-right:120px">修改密码</a>
<a href="{% url 'register'%}">注册</a>
</div>
</div>
</form>
<div class="sk-rotating-plane"></div>
<canvas class="particles-js-canvas-el" width="616" height="754" style="width: 100%; height: 100%;"></canvas>
</div>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>-->
<script src="{% static 'js/particles.min.js' %}"></script>
<script src="{% static 'js/app.js' %}"></script>
</body>
</html>
5.register.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
<style>
input{
width:300px;
height:30px;
padding:10px;
}
.i5{
font-size:20px;
}
span{
margin-right:50px;
}
button{
margin-top:30px;
width:60px;
height:35px;
text-align:center;
margin-right:50px;
}
span{
color:red;
}
.ii{
margin-top:30px;
}
</style>
</head>
<body>
<div class="i" style="width:500px;margin:50px auto;">
<h2>注册页面</h2>
<form action="" method="post" novalidate>
{% csrf_token %}
<div class="i1 ii">{{ form_obj.username }}
</div>
<span>{{ form_obj.username.errors.0 }}</span>
<div class="i2 ii">{{ form_obj.password }}
</div>
<span>{{ form_obj.password.errors.0 }}</span>
<div class="i3 ii">{{ form_obj.re_password }}
</div>
<span>{{ form_obj.re_password.errors.0 }}</span>
<div class="i4 ii">{{ form_obj.name }}
</div>
<span>{{ form_obj.name.errors.0 }}</span>
<div class="i5 ii">部门:{{ form_obj.department }}
</div>
<span>{{ form_obj.department.errors.0 }}</span>
<div class="submit">
<button>提交</button>
</div>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<script>
$('input').focus(function () {
$('span').text('')
})
</script>
</body>
</html>
6.change_pwd.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改密码</title>
<style>
{
margin:0;
}
input{
width:300px;
height:30px;
margin-bottom:20px;
padding:10px;
}
button{
width:60px;
height:35px;
text-align:center;
margin-right:50px;
}
span{
color:red;
}
.i5{
margin-bottom:15px;
}
</style>
</head>
<body>
<div class="i" style="width:500px;margin:50px auto;">
<h2>修改密码页面</h2>
<form action="" method="post" >
{% csrf_token %}
<div class="i1"><input type="text" name="username" value="" placeholder="请输入账号"></div>
<div class="i2"><input type="password" name="password" value="" placeholder="请输入密码"></div>
<div class="i3"><input type="password" name="new_password" value="" placeholder="请输入您的新密码"></div>
<div class="i4"><input type="password" name="re_new_password" value="" placeholder="请再次输入您的新密码"></div>
<div class="i5">
<span>{{ error }}</span>
</div>
<button>提交</button>
</form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<script>
$('input').focus(function () {
$('span').text('')
})
</script>
</body>
</html>
五、效果
具体字段功能不一一演示了