本文共 11590 字,大约阅读时间需要 38 分钟。
项目地址:https://github.com/ylpxzx/Login_DjangoAuth
自动跳转到登录页点击右上角的“气泡”按钮,未登录情况下,自动跳转到登录页面
pip install pillowpip install django-simple-captchapip install django-simpleuipip install six
项目名为loginproject,应用名为login
from django.db import models# Create your models here.class User(models.Model): gender=( ('male','男'), ('female','女'), ) name=models.CharField(max_length=128,unique=True) password=models.CharField(max_length=256) email=models.EmailField(unique=True) sex=models.CharField(max_length=32,choices=gender,default="男") c_time=models.DateTimeField(auto_now_add=True) #新增了has_confirmed字段,这是个布尔值,默认为False,也就是未进行邮件注册; has_confirmed = models.BooleanField(default=False) def __str__(self): return self.name class Meta: ordering=["-c_time"] verbose_name="用户" verbose_name_plural="用户"class ConfirmString(models.Model): ''' ConfirmString模型保存了用户和注册码之间的关系,一对一的形式; ''' #code字段是哈希后的注册码; code = models.CharField(max_length=256) user = models.OneToOneField('User', on_delete=models.CASCADE, ) c_time = models.DateTimeField(auto_now_add=True) def __str__(self): return self.user.name + ": " + self.code class Meta: ordering = ["-c_time"] verbose_name = "确认码" verbose_name_plural = "确认码"
INSTALLED_APPS = [ 'login', # 应用名 'simpleui', # 后台美化 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'captcha', # 图形验证码]
STATIC_URL = '/static/'STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static","static"),]
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR,'static','templates')], # 添加模板文件路径 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], 'builtins':['django.templatetags.static'], # 添加该行,不用在静态模板中,手动添加{% load static %} }, },]
可自行百度如何开启163邮箱的POP3/SMTP服务
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'EMAIL_HOST = 'smtp.163.com'EMAIL_PORT = 25EMAIL_HOST_USER = '填入自己的163邮箱'EMAIL_HOST_PASSWORD = '开启163邮箱POP3/SMTP服务后的授权密码'# 注册有效期天数CONFIRM_DAYS = 7
from django.contrib import adminfrom .models import *# Register your models here.class UserAdmin(admin.ModelAdmin): list_display = ('name','sex','email','password','c_time') list_filter = ['sex','name','c_time'] search_fields = ['sex','name','c_time']class ConfirmAdmin(admin.ModelAdmin): list_display = ('code','user','c_time')admin.site.register(User,UserAdmin)admin.site.register(ConfirmString,ConfirmAdmin)
在应用下创建forms.py文件
from django import formsfrom captcha.fields import CaptchaFieldclass UserForm(forms.Form): username = forms.CharField(label="用户名", max_length=128, widget=forms.TextInput(attrs={ 'class': 'form-control'})) password = forms.CharField(label="密码", max_length=256, widget=forms.PasswordInput(attrs={ 'class': 'form-control'})) captcha = CaptchaField(label='验证码')class RegisterForm(forms.Form): gender = ( ('male', "男"), ('female', "女"), ) username = forms.CharField(label="用户名", max_length=128, widget=forms.TextInput(attrs={ 'class': 'form-control'})) password1 = forms.CharField(label="密码", max_length=256, widget=forms.PasswordInput(attrs={ 'class': 'form-control'})) password2 = forms.CharField(label="确认密码", max_length=256, widget=forms.PasswordInput(attrs={ 'class': 'form-control'})) email = forms.EmailField(label="邮箱地址", widget=forms.EmailInput(attrs={ 'class': 'form-control'})) sex = forms.ChoiceField(label='性别', choices=gender) captcha = CaptchaField(label='验证码')
python manage.py makemigrationspython manage.py migrate
在应用下创建urls.py文件
from django.conf.urls import urlfrom .views import *# CBV模式urlpatterns = [ url(r'^index/', IndexView.as_view(),name='index'), url(r'^login/', LoginView.as_view(),name='login'), url(r'^register/', RegisterView.as_view(),name='register'), url(r'^logout/', LogoutView.as_view(),name='logout'), url(r'^confirm/$', UserConfirmView.as_view(),name='confirm'), url(r'^content/', ContentView.as_view(),name='content'),]
与项目名同名的目录下的urls.py文件
from django.conf.urls import urlfrom django.conf.urls import includefrom django.contrib import adminurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'',include('login.urls')), # 配置app,login的url url(r'^captcha', include('captcha.urls')), # 配置图形验证码路由]
import hashlibimport datetimefrom django.shortcuts import renderfrom django.shortcuts import redirectfrom . import modelsfrom django import formsfrom login import formsfrom django.conf import settingsfrom django.views.generic import Viewfrom functools import wrapsfrom django.utils.decorators import method_decoratorfrom django.core.mail import EmailMultiAlternatives# Create your views here.def hash_code(s, salt='mysite'): # 加盐 # 加密 h = hashlib.sha256() s += salt h.update(s.encode()) # update方法只接收bytes类型 return h.hexdigest()def make_confirm_string(user): # 激活确定 now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") code = hash_code(user.name, now) models.ConfirmString.objects.create(code=code, user=user,) return codedef send_email(email, code): # 邮箱发送 subject = '来自Mr Wolf的注册确认邮件' text_content = '''感谢注册Mr Wolf,专注于Django实战的博客分享!\ 如果你看到这条消息,说明你的邮箱服务器不提供HTML链接功能,请联系管理员!''' html_content = '''感谢注册Mr Wolf系统,\ 专注于Django实战的博客分享!
请点击站点链接完成注册确认!
此链接有效期为{}天!
'''.format('127.0.0.1:8000', code, settings.CONFIRM_DAYS) msg = EmailMultiAlternatives(subject, text_content, settings.EMAIL_HOST_USER, [email]) msg.attach_alternative(html_content, "text/html") msg.send()# session认证装饰器def login_check(func): @wraps(func) def wrapper(request): if not request.session.get('is_login', None): return redirect("/login/") else: return func(request) return wrapper# CBV模式class IndexView(View): ''' 首页 ''' def get(self,request): return render(request, 'login/index.html')class RegisterView(View): ''' 注册 ''' def get(self,request): register_form = forms.RegisterForm(request.POST) return render(request, 'login/register.html', { 'message': '','register_form':register_form}) def post(self,request): register_form = forms.RegisterForm(request.POST) if register_form.is_valid(): # 获取数据 username = request.POST.get('username','') password1 = request.POST.get('password1','') password2 = request.POST.get('password2','') email = request.POST.get('email','') sex = request.POST.get('sex','') if password1 != password2: # 判断两次密码是否相同 message = "两次输入的密码不同!" return render(request, 'login/register.html', { 'message': message, 'register_form': register_form}) else: same_name_user = models.User.objects.filter(name=username) same_email_user = models.User.objects.filter(email=email) if same_name_user: # 用户名唯一 message = '用户已经存在,请重新选择用户名!' return render(request, 'login/register.html', { 'message': message, 'register_form': register_form}) elif same_email_user: # 邮箱地址唯一 message = '该邮箱地址已被注册,请使用别的邮箱!' return render(request, 'login/register.html', { 'message': message, 'register_form': register_form}) else: # 当一切都OK的情况下,创建新用户 new_user = models.User() new_user.name = username new_user.password = hash_code(password1) # 使用哈希加密密码 new_user.email = email new_user.sex = sex new_user.save() code = make_confirm_string(new_user) send_email(email, code) message = '请前往注册邮箱,进行邮件确认!' return render(request, 'login/confirm.html', { 'message': message}) # 跳转到等待邮件确认页面。class LoginView(View): ''' 登录 ''' def get(self,request): login_form = forms.UserForm(request.POST) return render(request,'login/login.html',{ 'login_form':login_form}) def post(self,request): login_form = forms.UserForm(request.POST) message = "请检查填写的内容!" if login_form.is_valid(): username = request.POST.get('username','') password = request.POST.get('password','') try: user = models.User.objects.get(name=username) if not user.has_confirmed: message = "该用户还未通过邮件确认!" return render(request, 'login/login.html', { 'message': message,'login_form':login_form}) if user.password == hash_code(password): # 哈希值和数据库内的值进行比对 # 记录会话状态 request.session['is_login'] = True request.session['user_id'] = user.id request.session['user_name'] = user.name return redirect('/index/') else: message = "密码不正确!" except: message = "用户不存在!" return render(request, 'login/login.html', { 'message': message,'login_form':login_form})class LogoutView(View): ''' 退出 ''' def get(self,request): if not request.session.get('is_login', None): return redirect("/index/") request.session.flush() # 或者使用下面的方法 # del request.session['is_login'] # del request.session['user_id'] # del request.session['user_name'] return redirect("/index/")class UserConfirmView(View): ''' 邮箱激活认证 ''' def get(self,request): code = request.GET.get('code', None) try: confirm = models.ConfirmString.objects.get(code=code) except: message = '无效的确认请求!' return render(request, 'login/confirm.html', { 'message': message}) c_time = confirm.c_time now = datetime.datetime.now() if now > c_time + datetime.timedelta(settings.CONFIRM_DAYS): confirm.user.delete() message = '您的邮件已经过期!请重新注册!' return render(request, 'login/confirm.html', { 'message': message}) else: confirm.user.has_confirmed = True confirm.user.save() confirm.delete() message = '感谢确认,请使用账户登录!' login_form = forms.UserForm(request.POST) return render(request, 'login/login.html', { 'message': message, 'login_form': login_form})class ContentView(View): # 气泡页面视图,登录后才允许访问 @method_decorator(login_check) def get(self,request): message = '验证气泡显示' return render(request, 'content.html', { 'message': message})
到上下载参考
转载地址:http://igugn.baihongyu.com/