# =====> 用户注册与登录|找回密码
1.页面没有逻辑操作
from django.views.generic import TemplateView
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name="index.html"))
]
# 如果页面有逻辑操作就需要配置视图函数;
from django.shortcuts import render
def user_login(requet):
if request.method == "POST":
user_name = request.POST.get("username", "")
pass_word = request.POST.get("password", "")
2.authenticate用户认证方法
from django.contrib.auth import authenticate,login
# 验证用户名密码是否正确
user = authenticate(username=user_name, password=pass_word)
# login()方法
if user is not None:
login(request, user)
return render(request, "index.html", locals())
else:
return render(request, "login.html", locals())
# ======================================>>index.html
# ----->>> 在登录成功之后跳转首页
# 注册与登录的form就变成了登录状态,需要在前端做判断;
{% if request.user.is_authenticated %}
...
{% else %}
...
{% endif %}
# ===================================================
elif request.method == "GET":
return render(request, "login.html", locals())
3.自定义后台auth认证方法-->>> 通过邮箱或者用户名登录
# ①在settings.py文件中重载变量
AUTHENTICATION_BACKENDS = (
'users.views.CustomBackend', # 自定义类
)
# ②自定义认证方法
from django.contrib.auth.backends import ModelBakend
# UserProfile是用户表
from .models import UserProfile
# 将这个类配置到settings.py文件中
from django.db.models import Q
class CustomerBackend(ModelBackend):
# 传入两个关键词参数
def authenticate(self, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username=username)|Q(email=username))
# 存在数据库的用户名是加密的,所有不能get
# 通过user中的check_password()方法,检测密码是否正确
if user.check_password(password):
# 用户名密码正确,返回user对象
return user
# 如果get不到数据,或者多个数据,就返回异常
except Exception as e:
return None
4.基于类的用户登录
# views.py
from django.views.generic.base imoprt View
# View这视图类中,有类似http的get,post等方法
class LoginView(View):
def get(self, request):
return render(request, "login.html", locals())
def post(self, request):
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":"用户名密码错误"})
# urls.py
from django.views.generic import TemplateView
urlpatterns = [
url(r'login/$', LoginView.as_view(), name="login")
]
5.form表单验证
# ①myforms.py
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(
required=True,
)
password = forms.CharField(
required=True,
)
# 将验证成功之后的业务逻辑添加到视图中
# ②views.py
from django.views.generic.base imoprt View
# View这视图类中,有类似http的get,post等方法
class LoginView(View):
def get(self, request):
return render(request, "login.html", locals())
def post(self, request):
# 创建表单对象
login_form = LoginForm(request.POST)
if login_form.is_valid():
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":"用户名密码错误"})
else:
# 同时返回表单验证错误信息
return render(request, "login.html", {'login_form':login_form})
6.django中login()函数实现的原理
# session&cookie
# 请看相关博客补充
7.注册功能
# 1.显示注册页面
# views.py
from django.views.generic.base import View
class RegisterView(View):
def get(self, request):
return render(request, "register.html", locals())
# urls.py
from django.views.generic import TemplateView
urlpatterns = [
url(r'register', RegisterView.as_view(), name="register")
]
# 2.用于生成图片验证码的第三方库django-simple-captcha==0.4.6
pip install django-simple-captcha==0.4.6
# 添加到应用配置中
'captcha'
# 迁移生成表
# 配置urlconf
# 3.RegisterForm注册表单验证
from django import forms
from captcha.field import CaptchaField
class RegisterForm(forms.Form):
email = forms.EmailField(
required=True
)
password = forms.CharField(
required=True
)
# 验证码input框
captcha = CharField(
error_messages={"invalid":"验证码错误"}
)
# 4.在视图中操作表单验证逻辑
# views.py
from django.views.generic.base import View
from .myform import RegisterForm
class RegisterView(View):
def get(self, request):
register_form = RegisterForm()
return render(request, "register.html", locals())
def post(self, request):
register_form = RegisterForm(request.POST)
# 如果格式校验成功
if register_form.is_valid():
# 注册流程
# 取出表单输入数据
user_name = request.POST.get("email", "")
# 判断用户名是否存在
if UserProfile.objects.filter(email=user_name):
return render(request, "register.html", {'register_form':register_form}, {'msg':'用户已经存在'})
else:
password = request.POST.get("password", "")
# 创建模型类对象,给将数据存入数据库中
user_profile = UseProfile()
user_profile.username = user_name
user_profile.email = user_name
# 数据库中is_active字段来表示是否激活的状态
user_profile.is_active = False
# 密码加密
from django.contrib.auth.hashers import make_password
user_profile.password = make_password(pass_word)
user_profile.save()
# 发送邮箱激活链接
send_register_email(user_name, 'register')
# 发送成功
return render(request, "login.html)
else:
return render(request, "register.html", {'register_form':register_form})
# register.html
# 验证码input框
{{ register_form.captcha }}
# 5.发送邮箱激活链接
# 新建utils->email_send.py
from users.models import EmailVerifyRecord
def send_register_email(email, send_type='register'):
# 创建验证码对象
email_record = EmailVerifyRecord()
# 生成四个随机字符串
random_str = random_str(16)
# 将发送邮件的字段数据事先保存到数据库中
email_record.code = code
email_recode.email = email
email_recode.send_type = send_type
email_recode.save()
# 定义文件内容
email_title = ""
email_body = ""
if send_type == "0":
email_title = ""
email_body = "点击下面链接激活账号:http://127.0.0.1:8000/active/{0}.format(code)"
# 使用django内部函数直接发送邮件
from django.core.mail import send_mail
from 项目.settings import EMAIL_FROM
# 参数:subject, message, from_email, recipient_list...
send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
# 如果发送成功
if send_status:
pass
# 06-10 视频=======-=-=-=-=-=-=||||||||||||||||||||||||||||||~~~~~~~
# ===========================>>> 在settings.py文件中写入发送配置
EMAIL_HOST = "smtp.sina.com" # 复制相关邮箱客户端SMTP服务器的地址
EMAIL_PORT = 25
EMAIL_HOST_USER = "公司邮箱@sina.com"
EMAIL_HOST_PASSWORD = "*****密码"
EMAIL_USE_TLS = False
EMAIL_FROM = "公司邮箱@sina.com"
# ==============================================================
# 生成随机字符串的函数
import random
def random_str(num)
code = ''
for i in range(num):
add = random.choice([random.randrange(10), chr(random.randrange(65,91))])
code+=str(add)
return code
# EmailVerifyRecord表结构
# models.py
class EmailVerifyRecord(models.Model):
code = models.CharField(max_length=20, verbose_name="验证码")
email = models.EmailField(max_length=50, verbose_name="邮箱")
send_type = models.CharField(
verbose_name="验证码类型",
choices=(
('register', "注册"),
('find', "找回密码")
)
)
send_time = models.DateTimeField(verbose_name="发送时间", default=datetime.time())
# 6.激活邮箱
# urls.py
url(r'^active/(?P<active_code>.*)/$', ActiveUserView.as_view(), name='user_active')
# views.py
class ActiveUserView(View):
def get(self, request, active_code):
all_records = EmailVerifyRecord.objects.filter(code=active_code)
if all_records:
for record in all_records:
email = record.email
user = UserProfile.objects.get(email=email)
user.is_active = True
user.save()
else:
# 如果数据库中没有获取到active_code
return render(request , 'register_fail.html')
return render(request, "login.html")
# 再到登录login视图中,添加是否激活is_active的条件
from django.views.generic.base imoprt View
# View这视图类中,有类似http的get,post等方法
class LoginView(View):
def get(self, request):
return render(request, "login.html", locals())
def post(self, request):
# 创建表单对象
login_form = LoginForm(request.POST)
if login_form.is_valid():
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:
# 表示已激活
if user.is_active:
# 执行登录
login(request, user)
return render(request, "index.html")
else:
return render(request, "login.html", {"msg":"用户名未激活"})
else:
# 登录不成功
return render(request, "login.html", {"msg":"用户名密码错误"})
else:
# 同时返回表单验证错误信息
return render(request, "login.html", {'login_form':login_form})
8.找回用户密码
# 1.点击找回密码,页面提示输入用户名密码;
# 2.提交之后后台发送重置密码的链接;
# 3.重置密码之后跳转登录页面;
# ----------->> 1.发送重置密码链接
# views.py
class ForgetPwdView(View):
def get(self, request):
# 实例化form表单对象
forget_form = ForgetForm()
return render(request, "forgetpwd.html", {'forget_form':forget_form})
def post(self, request):
# 实例化form表单对象
forget_form = ForgetForm(request.POST)
if forget_form.is_valid():
email = request.POST.get()
send_register_email(email, 'find')
return render(request, "send_success.html")
else:
# 如果表单验证失败
return render(request, "forgetpwd.html", {'forget_form':forget_form})
# ------>>> email_send.py
# ====================================
elif send_type == "find":
email_title = "在线注册密码重置链接"
email_body = "请点击下面的链接重置密码:http://127.0.0.1:8000/reset/{0}.format(code)"
send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
if send_status:
pass
# ====================================
# urls.py
url(r'^forget/$', ForgetPwdView.as_view(), name="forget_pwd")
# myform.py
class ForgetForm(forms.Form):
email = forms.EmailField(required=True)
captcha = CaptchaField(error_messages={"invalid":"验证码错误"})
# forgetpwd.html
{{ forget_form.captcha}}
# send_success.html
<p>邮件发送成功!</p>
# ----------->> 2.重置密码
# urls.py
url(r'^reset/(?P<active_code>.*)/$', ResetView.as_view, name='reset_pwd')
# views.py
class ResetView(View):
def get(self, request, active_code):
all_records = EmailVerifyRecord.objects.filter(code=active_code)
if all_records:
for record in all_records:
email = record.email
return render(request , 'password_reset.html', {'email':email})
else:
# 如果数据库中没有获取到active_code
return render(request , 'register_fail.html')
return render(request, "login.html")
# reset.html
# 添加一个隐藏的输入框,给后台传递邮箱地址
<input type="hidden" value="{{email}}">
# myform.py
class ModifyPwdForm(forms.Form):
password1 = forms.CharField(required=True, min_length=5)
password2 = forms.CharField(required=True, min_length=5)
# post请求处理修改验证码的逻辑
from .myforms import ModifyPwdForm
class ModifyPwdView(View):
# 重新定义一个form表单类,而不是在ResetView中继续操作;
# 因为RestView需要传入一个active_code参数;
def post(self, request):
modify_forms = ModifyPwdForm(request.POST)
if modify_form.is_valid():
pwd1 = request.POST.get("password1", "")
pwd2 = request.POST.get("password2", "")
email = request.POST.get("email", "")
if pwd1 != pwd2:
return render(request, "password_reset.html", {"email":email})
user = UserProfile.objects.get(email=email)
user.password = make_password(pwd2)
user.save()
return render(request, "login.html")
else:
email = request.POST.get("email", "")
return render(request, "password_reset.html", {"email":emial, "modify_form":modify_form})
# urls.py
url(r'^modify_pwd', ModifyPwdView.as_view(), name="modify_pwd")
# password_reset.htl
...action="{% url 'modift_pwd' %}"
# 遗留问题:1.添加一个email_verify字段,表示这个链接是否用过,
# 在user.save()之后,设置email_verify=True;
# 再次点击就告诉用户,密码已经修改过了或者失效;
# 2.给验证码设置过期时间;