python2.0_day18_Django自带的用户认证模块的使用
用户验证
我们基于一个项目来学习利用Django框架中的user表实现用户认证
Django练习小项目:学员管理系统设计开发
项目需求:
1.分讲师\学员\课程顾问角色,
2.学员可以属于多个班级,学员成绩按课程分别统计
3.每个班级至少包含一个或多个讲师
4.一个学员要有状态转化的过程 ,比如未报名前,报名后,毕业老学员
5.客户要有咨询纪录, 后续的定期跟踪纪录也要保存
6.每个学员的所有上课出勤情况\学习成绩都要保存
7.学校可以有分校区,默认每个校区的员工只能查看和管理自己校区的学员
8.客户咨询要区分来源 学员管理系统表结构
#_*_coding:utf-8_*_
from django.db import models # Create your models here.
from django.core.exceptions import ValidationError from django.db import models
from django.contrib.auth.models import User class_type_choices= (('online',u'网络班'),
('offline_weekend',u'面授班(周末)',),
('offline_fulltime',u'面授班(脱产)',),
)
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(u"姓名",max_length=)
def __unicode__(self):
return self.name class School(models.Model):
name = models.CharField(u"校区名称",max_length=,unique=True)
addr = models.CharField(u"地址",max_length=)
staffs = models.ManyToManyField('UserProfile',blank=True)
def __unicode__(self):
return self.name class Course(models.Model):
name = models.CharField(u"课程名称",max_length=,unique=True)
price = models.IntegerField(u"面授价格")
online_price = models.IntegerField(u"网络班价格")
brief = models.TextField(u"课程简介")
def __unicode__(self):
return self.name class ClassList(models.Model):
course = models.ForeignKey('Course')
course_type = models.CharField(u"课程类型",choices=class_type_choices,max_length=)
semester = models.IntegerField(u"学期")
start_date = models.DateField(u"开班日期")
graduate_date = models.DateField(u"结业日期",blank=True,null=True)
teachers = models.ManyToManyField(UserProfile,verbose_name=u"讲师") #def __unicode__(self):
# return "%s(%s)" %(self.course.name,self.course_type) class Meta:
verbose_name = u'班级列表'
verbose_name_plural = u"班级列表"
unique_together = ("course","course_type","semester") class Customer(models.Model):
qq = models.CharField(u"QQ号",max_length=,unique=True)
name = models.CharField(u"姓名",max_length=,blank=True,null=True)
phone = models.BigIntegerField(u'手机号',blank=True,null=True)
stu_id = models.CharField(u"学号",blank=True,null=True,max_length=)
#id = models.CharField(u"身份证号",blank=True,null=True,max_length=)
source_type = (('qq',u"qq群"),
('referral',u"内部转介绍"),
('51cto',u"51cto"),
('agent',u"招生代理"),
('others',u"其它"),
)
source = models.CharField(u'客户来源',max_length=, choices=source_type,default='qq')
referral_from = models.ForeignKey('self',verbose_name=u"转介绍自学员",help_text=u"若此客户是转介绍自内部学员,请在此处选择内部学员姓名",blank=True,null=True,related_name="internal_referral")
# 我们知道一般在表中创建外键关联字段时,ForeignKey()外键关联的都是其他表,不是本表.
# 本项目中我们存在一个业务是需要关联本表的需求: 学员可以转介绍学员.
# 那么如何实现呢,就是在 ForeignKey('self'),verbose_name是在admin后台显示的字段名称.help_text就是提示信息.
# related_name这个注意了:只要是关联自己就必须有这个属性设置(因为当用forekey()关联其他表时,反向查询常规方法,而这种关联本表的foreignKey()反向查询就用related_name定义的值,这里就是internal_referral,用的时候作为字段使用)
# 比如,我要查张三介绍了的几个学员 '张三'.internal_referral course = models.ForeignKey(Course,verbose_name=u"咨询课程")
class_type = models.CharField(u"班级类型",max_length=,choices=class_type_choices)
customer_note = models.TextField(u"客户咨询内容详情",help_text=u"客户咨询的大概情况,客户个人信息备注等...")
status_choices = (('signed',u"已报名"),
('unregistered',u"未报名"),
('graduated',u"已毕业"),
) status = models.CharField(u"状态",choices=status_choices,max_length=,default=u"unregistered",help_text=u"选择客户此时的状态")
consultant = models.ForeignKey(UserProfile,verbose_name=u"课程顾问")
date = models.DateField(u"咨询日期",auto_now_add=True) class_list = models.ManyToManyField('ClassList',verbose_name=u"已报班级",blank=True) def __unicode__(self):
return "%s,%s" %(self.qq,self.name ) class ConsultRecord(models.Model):
customer = models.ForeignKey(Customer,verbose_name=u"所咨询客户")
note = models.TextField(u"跟进内容...")
status_choices = ((,u"近期无报名计划"),
(,u"2个月内报名"),
(,u"1个月内报名"),
(,u"2周内报名"),
(,u"1周内报名"),
(,u"2天内报名"),
(,u"已报名"),
)
status = models.IntegerField(u"状态",choices=status_choices,help_text=u"选择客户此时的状态") consultant = models.ForeignKey(UserProfile,verbose_name=u"跟踪人")
date = models.DateField(u"跟进日期",auto_now_add=True) def __unicode__(self):
return u"%s, %s" %(self.customer,self.status) class Meta:
verbose_name = u'客户咨询跟进记录'
verbose_name_plural = u"客户咨询跟进记录" class CourseRecord(models.Model):
course = models.ForeignKey(ClassList,verbose_name=u"班级(课程)")
day_num = models.IntegerField(u"节次",help_text=u"此处填写第几节课或第几天课程...,必须为数字")
date = models.DateField(auto_now_add=True,verbose_name=u"上课日期")
teacher = models.ForeignKey(UserProfile,verbose_name=u"讲师")
def __unicode__(self):
return u"%s 第%s天" %(self.course,self.day_num)
class Meta:
verbose_name = u'上课纪录'
verbose_name_plural = u"上课纪录"
unique_together = ('course','day_num') class StudyRecord(models.Model):
course_record = models.ForeignKey(CourseRecord, verbose_name=u"第几天课程")
student = models.ForeignKey(Customer,verbose_name=u"学员")
record_choices = (('checked', u"已签到"),
('late',u"迟到"),
('noshow',u"缺勤"),
('leave_early',u"早退"),
)
record = models.CharField(u"上课纪录",choices=record_choices,default="checked",max_length=)
score_choices = ((, 'A+'),
(,'A'),
(,'B+'),
(,'B'),
(,'B-'),
(,'C+'),
(,'C'),
(,'C-'),
(,'D'),
(-,'N/A'),
(-,'COPY'),
(-,'FAIL'),
)
score = models.IntegerField(u"本节成绩",choices=score_choices,default=-)
date = models.DateTimeField(auto_now_add=True)
note = models.CharField(u"备注",max_length=,blank=True,null=True) def __unicode__(self):
return u"%s,学员:%s,纪录:%s, 成绩:%s" %(self.course_record,self.student.name,self.record,self.get_score_display()) class Meta:
verbose_name = u'学员学习纪录'
verbose_name_plural = u"学员学习纪录"
unique_together = ('course_record','student')
学员公里系统表结构
我们首先创建一个新的Django project项目
django-admin startproject s12day18stu_crm
我们知道使用命令创建project时,默认是不会创建templates目录的,所以这里我们使用命令创建这个目录用于存放html模版文件
创建一个app,用来开发学员管理系统项目
python3. manage.py startapp app01
先把表结构拷贝进来.
首先我们看
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(u"姓名",max_length=)
def __unicode__(self):
return self.name
user字段用的是models.OneToOneField(User),这里的User是Django中用户验证模块
OneToOneField
这里user = models.OneToOneField(User),相当于做了一个外键,只是一般外键是1对多的,但是这里是1对1的,为什么1对1呢?
你想如果是普通的外键,假如有两个账户Alex1和Alex2 都外连同一个外键,那么问当我们用django中的这个账户登录时,到底登录到哪个账户呢?所以这里必须1对1,
mysql中是不能实现限制1对1的功能.所以这里OneToOneField()其实是在Django中实现的限制的.
那么我们为什么创建一个userprofile()还要用Django中的User表做外键呢?直接定义用户登录名和密码不就行了吗?问的好!
session的简单需求介绍
1.首先浏览器访问网页的连接属于短链接(非点击一次链接请求,服务器返回请求内容,然后就断开了),在点一次就属于心的请求.
2.我们知道当你访问一个网站,比如京东,加入你在登录界面输入用户名和密码后,成功登录到系统.
2. 当你在购买物品后,点击支付,这时候把请求发给服务端,服务端这时候接收到请求后,对于服务端只是一个请求,支付的前提是你已经是登录后的账户,但是服务器怎么知道?
基本上所有网站都是通过session来实现身份标记的.当你登录到网站后,服务端就会生成一个session(一个字符串),服务端在返回请求时把session返回给请求端.
那么这样一个生成session的过程,是需要我们进行代码实现的.所以我们使用Django中user模块,在验证的时候就实现了session的生成,
并且user模块不仅实现了生成session,同时还实现了密码的加盐加密.(加盐加密就是在md5加密的基础上在加一些我们自己的特定字符串.) 上面OneToOneField 和 session的知识点内容介绍完后,我们就可以创建这个app01这个应用的数据库了. 1. 首先创建一个s12day18stu_crm库(因为我们创建Django Project的时候的名字是s12day18stu_crm),其中要指定数据库的字符编码
create database s12day18stu_crm default CHARSET utf8;
2. 然周执行python3.5 manage.py migrate,第一次执行时不需要生成配置文件,因为默认是添加Django里的admin和auth表,差不多有9张表把.
3. 把app01 添加到settings.py文件里
4. 生成新的配置文件python3.5 manage.py makemigrations
5. 创建app01程序数据库 这些步骤都完成后,我们可以在数据库中查看到app01_开头的表,和Django后台系统使用的auth_ 开头的以及Django_开头的表
6. 开启Django服务
python3.5 manage.py runserver 127.0.0.1:8000
7. http://127.0.0.1:8000/admin访问后台,提示输入用户名和密码
8. 创建用户名和密码python3.5 manage.py createsuperuser
9. 把app01程序下的数据库表加到admin后台管理
from django.contrib import admin
# Register your models here.
from app01 import models
admin.site.register(models.Customer) # 客户表(学员表)
admin.site.register(models.ConsultRecord) #客户咨询跟进记录表
admin.site.register(models.ClassList) #班级表
admin.site.register(models.CourseRecord) # 班级上课记录表
admin.site.register(models.StudyRecord) # 学员学习记录表
admin.site.register(models.UserProfile) #用户表
admin.site.register(models.Course) #课程表
通过后台管理数据库
这里有两个点需要测试:
1. 客户表创建客户时,学员转介绍 选择本表里的其他学员
2. 班级上课记录表是班级与第几节课以及类型(网络\面授)联合唯一.然后学员学习在关联班级上课记录表,如果想知道某一条班级上课记录表有多少学生上课怎么办?
解决思路是,首先从班级上课记录表查 学员学习记录的条目是反向关联.然后我们就应该我们应该查询应该是学员学习记录表,且筛选条件为班级上课记录,这里应该定义一个Django admin后台的action动作 初始化 该班级下的所有学员创建一条新课程的学员学习记录.
然后在查看学员学习记录时应该通过帅选filter选择某一条班级课程记录. 学习视频中,老师实现了,后台管理界面中首先按照学校分类,点进去后才是 客户表\客户咨询跟进记录表\班级表....课程表.
但是视频中如何实现未看到,需要找高人指点. 紧接着学习的知识点:用户认证的实现
我们先给app01写一个首页:
1.在urls.py写一个URL
from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.index),
]
2.在views里定义index
def index(request):
return render(request,'index.html')
3.在templates目录下创建index.html
<body>
Welcome To Oldboy CRM
</body>
4. 访问http://127.0.0.1:8000查看访问结果
OK的
那么怎么实现只有登录后才能看到这个页面?
如果有N多个页面都需是需要登录后才能访问的,我们应该在每一个视图里都加一个if else判断,判断的内容是request里的session内容是不是和服务器一直(当然前提还得写一个登录后生成session的函数).
简单点的方法是就写一个验证函数,然后在视图里,每一个函数前面加一个装饰器.
实现思路就是这样,而在于Django中,这个装饰器Django已经写好了.我们直接调用就可以了 5.更改views.py文件,加入验证的装饰器
from django.shortcuts import render
from django.contrib.auth.decorators import login_required #引入登录验证模块 # Create your views here.
@login_required
def index(request):
return render(request,'index.html')
然后登录测试:

结果:我们访问的是http://127.0.0.1:8000却被转到:http://127.0.0.1:8000/accounts/login/?next=/
这是因为我们没登录,Django默认把URL转到这个URL,所以我们应该在这个URL里写一个登录页面
6.写一个登录页面,URL为:http://127.0.0.1:8000/accounts/login/
添加urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.index),
url(r'^accounts/login/$', views.acc_login),
]
编辑app01/views.py
def acc_login(request):
return render(request,'login.html')
创建templates/login.html
我们先看index.html
<body>
<h1>oldboy CRM</h1>
{% block page-container%}
Welcome To Oldboy CRM
{% endblock %}
</body>
我们创建login.html直接让它即成index.html,然后在重新block里的内容
查看login.html内容如下:
{% extends 'index.html' %}
这时候我们访问网址:http://127.0.0.1:8000/accounts/login/?next=/ 结果如下:

确认无误时,我们开始重写block,如下:
{% extends 'index.html' %}
{% block page-container %}
<form action="" method="post"> {% csrf_token %}
Username:<input type="text" name="username">
Password:<input type="password" name="password">
<input type="submit" value="Log me in">
</form>
{% endblock %}
访问测试如下:

这时候我们随便输入用户名和密码就可以提交后台了.
接下来我们就需要在views里对login.html中post的提交内容进行处理了
def acc_login(request):
if request.method == 'POST':
print(request.POST)
return render(request,'login.html')
这时候我们在浏览器输入用户名和密码,在Django的命令行窗口输出如下内容:
<QueryDict: {'username': ['admin'], 'password': ['admin123'], 'csrfmiddlewaretoken': ['p0P8hrImljJ7HVJYIYLVgpGniT70MicK']}>
我们看到用户名和密码都被打印出来了.前面我们说过一般网站验证都不会名文验证,都是加盐加密.也就是收到用户输入的内容后,传到后台,后台在进行加盐加密封装后与数据库里的记录做对比.
前面说过我们此节用户验证的部分要使用Django自带的而不是自己写.所以我们想把用户输入进来的账户进行验证,就要用到Django自带的验证方法..
于是代码如下
from django.shortcuts import render,redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate
def acc_login(request):
if request.method == 'POST':
print(request.POST)
# 取出用户名和密码,实例化Django自己的用户验证实例
user = authenticate(username = request.POST.get('username'),
password = request.POST.get('password')
)
if user is not None: # 如果用户不为空,则认证成功
# return render() # 当登录成功后,就不不是render一个页面了,应该跳转到首页了.
return redirect('/') # 验证成功后,跳转到首页url
else:
# 如果登录失败,返回报错信息
login_err = 'Wrong username or password'
return render(request,'login.html',{'login_err':login_err})
return render(request,'login.html')
定义login.html
{% extends 'index.html' %}
{% block page-container %}
<form action="" method="post">{% csrf_token %}
Username:<input type="text" name="username">
Password:<input type="password" name="password">
<input type="submit" value="Log me in">
</form>
<div>
{% if login_err %}
<p style="color: red"> {{login_err}}</p>
{% endif %}
</div>
{% endblock %}
这时候我们访问首页http://127.0.0.1:8000/,首先会跳转到登录页面http://127.0.0.1:8000/accounts/login/?next=/
输入错误的密码,提示错误,如下:

当我们输入正确的用户名和密码,结果没有跳转(不是没跳转,只是又再次跳转到验证页面).为什么?
因为我们只是在login中验证了账户的用户名和密码.而没有把session存下来.所以我们应该把session存下来
from django.shortcuts import render,redirect,HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate,login #新导入login
# 引入Django自带的用户验证模块
# Create your views here.
@login_required
def index(request):
return render(request,'index.html') def acc_login(request):
if request.method == 'POST':
print(request.POST)
# 取出用户名和密码,实例化Django自己的用户验证实例
user = authenticate(username = request.POST.get('username'),
password = request.POST.get('password')
)
if user is not None:
login(request,user) # 实例化login,此时就会生成session,并保存到request
return redirect('/') #
# return HttpResponseRedirect('/') #也可以用这个跳转
else:
# 如果登录失败,返回报错信息
login_err = 'Wrong username or password'
return render(request,'login.html',{'login_err':login_err})
return render(request,'login.html')
我们再次访问测试:
-》 
跳转成功了,问题又来了,我如果想在首页中显示我的用户名,就像京东,右上角那样,未登录显示,"登录",登录后显示"用户名"
我们首先想到的就是在模版html判断是不是登录,代码如下:
<h1>oldboy CRM</h1>
{% block page-container%}
Welcome To Oldboy CRM
<div>
{% if request.user.is_authenticated %}
<!--这里要注意,request在views中会自动返回,无论你在views视图里return时有没有返回-->
<!--<span>{{ request.user }}</span>-->
<!--这里显示的是用户名,想显示全名如下-->
<span>{{ request.user.userprofile.name }}</span>
{% else %}
<span>登录/注册</span>
{% endif %}
</div>
{% endblock %}
</body>
这时候我们就可以在页面看到用户全名了.
接下来我们来看如何退出
现在index.html写一个退出的按钮
<body>
<h1>oldboy CRM</h1>
{% block page-container%}
Welcome To Oldboy CRM
<div>
{% if request.user.is_authenticated %}
<!--这里要注意,request在views中会自动返回,无论你在views视图里return时有没有返回-->
<!--<span>{{ request.user }}</span>-->
<!--这里显示的是用户名,想显示全名如下-->
<span>{{ request.user.userprofile.name }}</span>
{% else %}
<span>登录/注册</span>
{% endif %}
</div>
<a href="/accounts/logout/">退出系统</a>
{% endblock %}
</body>
添加urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.index),
url(r'^accounts/login/$', views.acc_login),
url(r'^accounts/logout/$', views.acc_logout),
]
在app01/views.py添加退出视图
from django.contrib.auth import authenticate,login,logout # 导入logout
def acc_logout(request):
logout(request)
return HttpResponseRedirect('/')
页面测试结果:
-》
python2.0_day18_Django自带的用户认证模块的使用的更多相关文章
- (30)auth模块(django自带的用户认证模块)
Auth模块是Django自带的用户认证模块: 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的 ...
- Django之auth模块用户认证模块
一.Auth模块 1)auth模块是什么.登录后台使用的账号密码,则就是使用的auth模块创建的表 Auth模块是Django自带的用户认证模块: 我们在开发一个网站的时候,无可避免的需要设计实现网站 ...
- Django自带的用户认证
1. 创建超级用户 python manage.py createsuperuser 2. 认证 校验用户名和密码 obj = auth.authenticate(request,user ...
- 6月29日学习总结 Django自带的用户认证
Django自带的用户认证 我们在开发一个网站的时候,无可避免的要设计.实现网站的用户系统.此时我们需要实现包括但不限于用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. D ...
- Django自带的用户认证auth模块
一.介绍 基本上在任何网站上,都无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能. 使用Django,我们可以不需要自己写这些功能,因为Dj ...
- django自带的用户认证和form表单功能
一.用户认证 1.用户认证方法 1.ajango自带用户认证功能,只需要引入相应的模块就可以使用,但是前提是必须使用ajango自带的auth_user表,并且需要把用户相关信息存放在该表中. 2.引 ...
- 基于 django 自带的用户认证进行用户认证
django admin 默认已经存在了一个用户认证,这个时候可以偷个小懒,直接用 django 自带的,就不需要自己写用户认证了 1.目录结构: 2.代码 在 settings.py 中添加一行 # ...
- Django用户认证模块中继承AbstractUser与AbstractBaseUser重写User表的区别
AbstractUser和AbstractBaseUser看起来十分相似,如果你不熟悉djiango的auth重写User,那你很容易弄错,导致一堆bug. 我们查看AbstractUser的源码得知 ...
- Django——Auth模块(用户认证模块)
1.Auth模块简介 auth模块是对登录认证方法的一种封装,之前我们获取用户输入的用户名及密码后需要自己从user表里查询有没有用户名和密码符合的对象. 而有了auth模块之后就可以很轻松的去验证用 ...
随机推荐
- C#与C++区别
C#是三大主流OOP(面向对象编程)语言(C++,Java,C#)之一,也是最新的一种,其中必然借鉴了前两者的长处,“否则它的缔造者就该打屁股”——候捷语,见<C#Primer中文版>的译 ...
- java 接口调用
生产中遇到过这种问题,记录下java的接口调用问题. 一种是json方式: public static String sendPost(String url, JSONObject obj)throw ...
- 利用struts2<s:token>标签防止用户重复提交
当用户填写完表单后,在提交过一次后,若用户做如下操作比如再次点击提交.刷新页面.提交页面呈现后点击后退按钮,都会导致表单重复提交.如果信息需要存储到后台数据库中,重复提交就会再次向数据库中插入用户信息 ...
- 查看局域网其它电脑的计算机名和IP
一.下面脚本可查看局域网中的电脑计算机名和IP,保存下面文本至记事本.后缀改成bat COLOR 0A CLS @ECHO Off Title 查询局域网内在线电脑IP :send @ECHO off ...
- 【C#】删除集合(Collection)里的元素(Item)
问题:C#中如果想要删除一个集合中的所有元素,直接for循环边读边删除是不可行的.因为每删除一个元素,后面的元素就会往前排,即它们的索引会向前-1,然后i还是正常的自增,就会跳过下一个元素. // 错 ...
- Spring InitializingBean和ApplicationListener<ContextRefreshedEvent>
事件机制作为一种编程机制,在许多语言中都提供了支持.JAVA语言也不例外,java中的事件机制的参与者有3种角色: 1.event object 2.event source 3.event list ...
- linux后台运行jar程序
Linux 运行jar包命令如下: 方式一:java -jar XXX.jar特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出那如何让窗口不锁定? 方式二java ...
- OC基础--常用类的初步介绍与简单使用之NSDate
一.创建一个时间 NSDate *date = [NSDate date]; // 打印出的时间是0时区的时间(北京--东八区) NSLog(@"%@",date); 二.日期格式 ...
- 记录github 免登陆用户名密码方式
1.https 代码模式切换为ssh模式: (本博客有文章介绍) 2.~/.ssh/github_rsa.pub 内容添加到github “config“ 目录下面 3.配置~/.ssh/config ...
- Uncaught (in promise) Provided element is not within a Document
今天在使用html2canvas生成海报的时候,发现报了个如下图所示的错误: 发生这个错误的本质原因是在调用html2canvas的时候传递的是jQuery对象,而不是DOM原生对象. 开始的时候我是 ...