自定义用户认证

目的:实现Django自定义的认证系统,在生产环境都是根据此代码进行定制的

步骤:

  1.在settings文件中配置要使用的类

                 #命名规则 app名称.类名      
AUTH_USER_MODEL = 'crm.UserProfile'

  2.在crm app下的models文件中加入Django官方的用户认证

from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser,PermissionsMixin
)
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
class UserProfileManager(BaseUserManager):
def create_user(self, email, name, password=None):
    #创建用户根据UserProfile中的字段,输入
if not email:
raise ValueError('Users must have an email address') user = self.model(
email=self.normalize_email(email),
name=name,
) user.set_password(password)
user.save(using=self._db)
return user def create_superuser(self, email, name, password):
    #创建超级用户根据UserProfile中的字段,输入
user = self.create_user(
email,
password=password,
name=name,
)
user.is_admin = True
user.save(using=self._db)
return user class UserProfile(AbstractBaseUser,PermissionsMixin):
#使用Django自带的登录系统,可以自定义一些字段,例如邮箱,密码,用户名
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
password = models.CharField(_('password'), max_length=128,help_text = mark_safe('<a href="password/">修改密码</a>')) name = models.CharField(max_length=32)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
  
  #在创建用户的时候调用该方法进行用户的创建
objects = UserProfileManager() USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name'] def get_full_name(self):
# The user is identified by their email address
return self.email def get_short_name(self):
# The user is identified by their email address
return self.email def __str__(self): # __unicode__ on Python 2
return self.email def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
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
return True @property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: active users are staff
return self.is_active class Meta:
verbose_name_plural = '用户'

  3.在crm app下的admin中

from django import forms
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from crm.models import UserProfile class UserCreationForm(forms.ModelForm):
  #在Django Admin页面中用户创建的表单展示
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) class Meta:
#展示的model对象和字段
model = UserProfile
fields = ('email', 'name') def clean_password2(self):
#判断两次输入的密码是否一致
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2 def save(self, commit=True):
     #保存用户到数据库
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user class UserChangeForm(forms.ModelForm):
#在Django Admin页面中用户修改的表单展示
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField() class Meta:
     #展示的model对象和字段  
model = UserProfile
fields = ('email', 'password', 'name', 'is_active', 'is_admin') def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"] class UserProfileAdmin(BaseUserAdmin):
#在在Django Admin页面中配置的admin_class
# The forms to add and change user instances
form = UserChangeForm #调用修改用户的表单
add_form = UserCreationForm #调用创建用户的表单 # The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'name', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('name',)}),
('Permissions', {'fields': ('is_admin','is_active','user_permissions',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'name', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ('groups','user_permissions') admin.site.unregister(Group)
#把models对象中的model对象和admin_class对象组合起来
admin.site.register(models.UserProfile,UserProfileAdmin)

  4.在king_admin中实现修改密码的功能

 在king_admin的urls.py中配置

url(r'^(\w+)/(\w+)/(\d+)/change/password/$',views.password_reset,name='password_reset'),

 在king_admin中的king_admin.py中配置

class UserAdmin(BaseAdmin):
list_display = ['email','name'] #首页展示的字段
readonly_fields = ['password',] #只读字段
modelfrom_exclude_fields = ['last_login','is_superuser','groups','user_permissions'] #不展示的字段

 在views函数中开发该模块

def password_reset(request,app_name,table_name,obj_id):
'''动态修改密码'''
#获取admin_class类和要修改密码的对象
admin_class = king_admin.enabled_admins[app_name][table_name]
model_obj = admin_class.model.objects.get(id=obj_id)
errors = {}
if request.method == 'POST':
#获取前端页面的两个值,密码和新密码
_password1 = request.POST.get('password1')
_password2 = request.POST.get('password2')
#如果两次密码相同,并且长度大于5位,则调用父类的方法保存密码,同时入库,最后返回到展示页面
if _password1 == _password2:
if len(_password2) > 5:
model_obj.set_password(_password1)
model_obj.save()
#保存成功则跳转到展示页面进行展示
return redirect(request.path.rstrip('password/'))
else:
errors['invalid_password'] = '密码长度不足6位'
else:
errors['invalid_password'] = '两次密码不一致'
return render(request,'king_admin/password_reset.html',{'model_obj':model_obj})

  5.在forms.py中将不需要展示的字段写到exclude上

class Meta:
model = admin_class.model
fields = '__all__'
exclude = admin_class.modelfrom_exclude_fields #排除的字段

  6.前端页面

  本质上是一个form表达,展示用户的用户名,然后用户填写密码和新密码之后提交到views的方法中进行修改密码的操作

{% extends 'king_admin/table_index.html' %}

{% block container %}
<div class="row">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">重置用户{{ model_obj.name }}密码</h3>
</div>
<div class="panel-body">
<form method="post" class="form-horizontal">
{% csrf_token %}
<div class="form-group">
<label class="col-sm-1" style="font-weight:normal">
用户名:
</label>
<div class="col-sm-3">
<input class="form-control" type="text" value="{{ model_obj.email }}" disabled>
</div>
</div>
<div class="form-group">
<label class="col-sm-1" style="font-weight:normal">
密码:
</label>
<div class="col-sm-3">
<input class="form-control" type="password" name="password1">
</div>
</div>
<div class="form-group">
<label class="col-sm-1" style="font-weight:normal">
重复密码:
</label>
<div class="col-sm-3">
<input class="form-control" type="password" name="password2">
</div>
</div>
<div>
<ul style="color:red">
{% for k,v in errors.items %}
<li>{{ k }}-{{ v }}</li>
{% endfor %}
</ul>
</div>
<input type="submit" class="btn btn-info" style="margin-left:110px" value="提交">
<input type="reset" class="btn btn-danger" style="margin-left:30px" value="重置">
</form>
</div>
</div>
</div>
{% endblock %}

自定义用户登录

  目的:利用Django提供的组件,实现自己的用户认证系统,包括登录,登出和利用装饰器实现方法的登录校验

  1.在settings文件中配置登录url的路径

LOGIN_URL = '/'

  2.在入口的app中配置url

  3.在views中开发登录,登出和首页的模块

from django.shortcuts import render,redirect
from django.contrib.auth import login,authenticate,logout
# Create your views here. def account_login(request):
errors = {}
if request.method == 'POST':
#获取前端表单的值
_email = request.POST.get('email')
_password = request.POST.get('password')
#使用Django自带的用户认证
user = authenticate(username=_email,password=_password)
if user:
#登录成功则进行跳转,如果有next_url则跳转到下一个页面,否则跳转到首页
login(request,user)
next_url = request.GET.get('next','')
if next_url:
return redirect(next_url)
else:
return redirect('/index/')
else:
errors['error'] = '用户名密码不正确'
return render(request,'login.html',{'errors':errors}) def account_logout(request):
#用户登出
logout(request)
return redirect('/account/login/') def index(request):
return render(request,'index.html')

  4.在需要登录校验的方法上,加上@login_required装饰器

from django.contrib.auth.decorators import login_required

@login_required
def index(request):
return render(request, 'king_admin/table_index.html',{'table_list':king_admin.enabled_admins})

  5.前端页面,form表单以post的方式向后台发送用户名和密码,后端的views中相应的方法进行校验

  {% extends 'base.html' %}

  {% block body %}
<div class="row">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">登录CRM系统</h3>
</div>
<div class="panel-body ">
<form class="form-horizontal" method="post">{% csrf_token %}
<div class="form-group">
<label class="col-sm-1" style="font-weight:normal">
邮箱:
</label>
<div class="col-sm-3">
<input type="email" name="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>
</div>
</div>
<div class="form-group">
<label class="col-sm-1" style="font-weight:normal">
密码:
</label>
<div class="col-sm-3">
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
</div>
</div>
{% if errors %}
<span style="color: red">{{ errors.error }}</span>
{% endif %}
<button class="btn btn-info" style="margin-left:113px" type="submit">登陆</button>
<button class="btn btn-danger" type="reset">清空</button>
</form>
</div>
</div>
</div> {% endblock %}

  6.在index首页集成用户登出同时生成动态的菜单链接,点击跳转到相应的页面

  登出

<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{ request.user.name }}</a>
<ul class="dropdown-menu" role="menu">
<li><a href="{% url 'account_logout' %}">注销</a></li>
</ul>
</li>

  动态菜单生成

<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar"> {% for role in request.user.roles.all %}
{% for menu in role.menus.all %}
<li>
{# 如果是绝对路径的url type=1,直接显示url的名称,如果是相对路径的url type=0,则动态根据url的别名来获取url #}
<a href="{% if menu.url_type == 0 %}{% url menu.url_name %}{% else %}{{ menu.url_name }}{% endif %}">{{ menu.name }}</a>
</li>
{% endfor %}
{% endfor %}
</ul> </div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{% block page-content %} {% endblock %}
</div>
</div>
</div>

Python CRM项目八的更多相关文章

  1. Python CRM项目二

    一.准备工作 如果没有配置基本的项目,请参考 http://www.cnblogs.com/luhuajun/p/7771196.html 当我们配置完成后首先准备我们的app 创建2个app分别对应 ...

  2. Python CRM项目一

    开发环境: 语言Python3.X以上 MTV WEB框架 Django 前端框架 jQuery+bootstrap 数据库 MySQL 运行环境 安装Python3.x 安装Django 除IE8以 ...

  3. Python CRM项目三

    1.分页: 分页使用Django内置的分页模块来实现 官方的分页案例 from django.core.paginator import Paginator, EmptyPage, PageNotAn ...

  4. python实践项目八:生成随机试卷文件

    描述:匹配美国50个州的首府. 下面是程序需要完成的任务: • 创建35 份不同的测验试卷. • 为每份试卷创建50 个多重选择题,次序随机. • 为每个问题提供一个正确答案和3 个随机的错误答案,次 ...

  5. Python CRM项目七

    仿照Django Admin实现对readonly的字段进行设置 功能点: 1.页面不可进行更改 2.如果改变html代码中的值,则需要进行后端的数据库数据校验 3.可以对某些字段进行自定制校验规则 ...

  6. Python CRM项目六

    自定义Django Admin的action 在Django Admin中,可以通过action来自定义一些操作,其中默认的action的功能是选中多条数据来进行删除操作 我们在king_admin中 ...

  7. Python CRM项目四

    实现Django Admin的多对多的复选框效果 效果:左边显示的是未选中的字段,右边显示的是已选中的字段,两边点击的标签可以互相更换 首先在king_admin.py中增加filter_horizo ...

  8. 2015老男孩Python培训第八期视频教程

    2015老男孩Python培训第八期视频教程,希望您通过本教程的学习,能学会常用方法和技巧.教程从基础知识开始讲解一直到后期的案例实战,完全零基础学习,从初学者的角度探讨分析问题,循序渐进由易到难,确 ...

  9. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

随机推荐

  1. UINavigationController 返回手势与 leftBarButtonItem

    UINavigationController 返回手势与 leftBarButtonItem UINavigationController 自带从屏幕左侧边缘向右滑动的返回手势,可以通过这个手势实现 ...

  2. Java与算法之(5) - 老鼠走迷宫(深度优先算法)

    小老鼠走进了格子迷宫,如何能绕过猫并以最短的路线吃到奶酪呢? 注意只能上下左右移动,不能斜着移动. 在解决迷宫问题上,深度优先算法的思路是沿着一条路一直走,遇到障碍或走出边界再返回尝试别的路径. 首先 ...

  3. cs231n spring 2017 lecture9 CNN Architectures 听课笔记

    参考<deeplearning.ai 卷积神经网络 Week 2 听课笔记>. 1. AlexNet(Krizhevsky et al. 2012),8层网络. 学会计算每一层的输出的sh ...

  4. JDBC(二)之JDBC处理CLOB和BLOB及事务与数据库元数据获取

    前面大概介绍了JDBC连接数据库的过程,以及怎么操作数据库,今天给大家分享JDBC怎么处理CLOB和BLOB存储图片的事情,以及JDBC怎么去处理事务.怎么在插入数据的时候生成主键返回值 一.JDBC ...

  5. 【Java学习笔记之十七】Java中普通代码块,构造代码块,静态代码块区别及代码示例分析

    //执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 //普通代码块:在 ...

  6. hbmy周赛1--C

    C - Exam Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit St ...

  7. cesium编程入门(四)界面介绍及小控件隐藏

    感性认识 界面介绍,viewer Geocoder : 查找位置工具,查找到之后会将镜头对准找到的地址,默认使用bing地图 Home Button :视角返回初始位置. Scene Mode Pic ...

  8. linux 下CentOS 下 npm命令安装gitbook失败的问题

    运行环境 linux 服务器:CentOS 7.0 系统:安装了nodejs :使用 npm 安装 gitbook 出现错误提示: npm install -g gitbook-cli symbol ...

  9. Netty5序章之BIO NIO AIO演变

    Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使 ...

  10. Content Provider Test过程中遇到的坑

    Content Provider(内容提供器) 一.什么是Content Provider? 直接贴官方文档简介图,笔者太懒了,而且 坑 不在这