django2.2 用户登录练习完整版(待改善)

主要配置:

settings.py配置:

#数据库配置
import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysite',
        'HOST': '47.104.124.214',
        'USER': 'root',
        'PASSWORD': 'django',
        'PORT': '3306',
    }
}


#session共享
# 配置session使用redis
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://47.104.124.214:6379', # 指明使用redis的1号数据库后面加/库名即可
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
             "PASSWORD": "",
        },
    },
}

# session的存储配置
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
# 设置session失效时间,单位为秒
SESSION_COOKIE_AGE = 60*5


# 邮件配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com'
EMAIL_PORT = 25
EMAIL_HOST_USER = '1335234172@qq.com'
EMAIL_HOST_PASSWORD = 'nekxangczvxpgbii'
# 注册有效期天数
CONFIRM_DAYS = 7

项目urls.py

from django.contrib import admin
from django.urls import path,include
from Registration import views
urlpatterns = [
    path('',include('Registration.urls')),
    path('admin/', admin.site.urls),
    path('Registration/',include('Registration.urls')),
    path('login/',views.login),
    path('register/',views.register),
    path('logout/',views.logout),
    path('captcha/', include('captcha.urls')),
    path('confirm/', views.user_confirm),
]

app admin.py

from django.contrib import admin
from . import models
# Register your models here.
admin.site.register(models.User)
admin.site.register(models.ConfirmString)

models.py

from django.db import models

class User(models.Model):
    gender = (('male','男'),('female','女'))
    user = models.CharField(verbose_name=u'姓名',max_length=128,unique=True)
    passwd = models.CharField(verbose_name=u'密码',max_length=128)
    email = models.EmailField(verbose_name=u'邮箱',unique=True)
    sex = models.CharField(verbose_name=u'性别',max_length=32,choices=gender,default="男")
    c_time = models.DateTimeField(verbose_name=u'创建时间',auto_now_add=True)
    mod_date = models.DateTimeField(verbose_name=u'修改日期', auto_now=True)
    confiremd = models.BooleanField(verbose_name=u'确认',default=False)
    def __str__(self):
        return self.user

    class Meta:
        ordering = ['-c_time']
        db_table = 'User'
        verbose_name = '用户表_[User]'
        verbose_name_plural = '用户表_[User]'

    #verbose_name=u'姓名',用于在admin界面添加正好时友好显示。不写添加账号会显示:字段名称
    #unique唯一性
    #auto_now无论是你添加还是修改对象,时间为你添加或者修改的时间。
    #auto_now_add为添加时的时间,更新对象时不会有变动。
    #choice只能选择'男'或者'女'.默认为男
    #__str__是python的一个魔幻方法。作用于django管理界面用于将数据库中的记录展示为易读的字符串。
    #Meta类用于定义表名称。默认表名称为'app名称_表名称',db_table用于指定表名
    #ordering 用于指定一个字段,按照升序或降序对数据进行排序。指定的字段名称前加'-'表示递减,若没有加表示升序,若加'?'表示随机.
    #verbose_name用于在admin界面单数显示,verbose_name_plural复数形式显示。中文单数复数一般不做区别。
    #verbose类似于User表在admin界面的显示形式。类似于别名
class ConfirmString(models.Model):
    code = models.CharField(max_length=256)
    user = models.OneToOneField('User',on_delete=models.CASCADE)
    c_time = models.DateTimeField(auto_now_add=True)
    #on_delete=models.CASCADE主外关系键中,级联删除,也就是当删除主表的数据时候从表中的数据也随着一起删除
    def __str__(self):
        return self.user_id + ": "+self.code
    class Meta:
        ordering = ['-c_time']
        db_table = 'ConfirmString'
        verbose_name = "确认表_[ConfirmString]"
        verbose_name_plural = "确认表_[ConfirmString]"
        

app urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('', views.index,name='index'),
]

views.py

from django.shortcuts import render,redirect
from django.http import HttpResponse
from . import models
import hashlib
import datetime
from django.conf import settings




def send_email(email, code):
    from django.core.mail import EmailMultiAlternatives
    subject = '来自bestyunyan.com的注册确认邮件'
    text_content = '''感谢注册bestyunyan.com,这里是王云龙的博客站点,专注于Python、Django学习技术的分享!\
                    如果你看到这条消息,说明你的邮箱服务器不提供HTML链接功能,请联系管理员!'''

    html_content = '''
                    <p>感谢注册<a href="http://{}/confirm/?code={}" target=blank>www.bestyunyan.com</a>,\
                    这里是王云龙的博客站点,专注于Python、Django学习技术的分享!</p>
                    <p>请点击站点链接完成注册确认!</p>
                    <p>此链接有效期为{}天!</p>
                    '''.format('127.0.0.1', code, settings.CONFIRM_DAYS)

    msg = EmailMultiAlternatives(subject, text_content, settings.EMAIL_HOST_USER, [email])
    msg.attach_alternative(html_content, "text/html")
    msg.send()

#定义hash_code方法用于生成code
def hash_code(s, salt='mysite'):
    h = hashlib.sha256()
    s += salt
    h.update(s.encode())
    return h.hexdigest()

def make_confirm_string(user):
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    code = hash_code(user.user, now)
    models.ConfirmString.objects.create(code=code, user=user,)
    return code

def index(request):
    if not request.session.get('is_login',None):
        return redirect('/login/')
    # return HttpResponse('Hello, world. You\'re at the polls index.')
    return render(request,'index.html')

def login(request):
    if request.session.get('is_login',None):
        return redirect('/')
    if request.method == "POST":
        user = request.POST.get('username')
        password = request.POST.get('password')
        message='请检查填写内容!'
        print('------user:%s,password:%s------'%(user,password))
        if user.strip() and password:
            try:
                u=models.User.objects.get(user=user)
                #a=models.table_name.objects.get(xx=xx,yy=yy)
                #返回一个数据对象.获取数据对象的某一个属性字段值通过点的方式获取如:
                print('---数据库用户:%s,密码:%s,注册日期:%s'%(u.user,u.passwd,u.c_time))
            except Exception as f:
                print(f)
                message = '用户不存在!'
                return render(request,'login/login.html',{'message':message})
            if not u.confiremd:
                message = '用户未确认,请前往邮箱确认!'
                return render(request,'login/login.html',{'message':message})
            if u.passwd == password:
                request.session['is_login'] = True
                request.session['user_id'] = u.id
                request.session['user_name'] = u.user
                request.session['user_email'] = u.email

                return redirect('/')
            else:
                message = '密码不正确'
                return render(request,'login/login.html',{'message':message})
        return render(request,'login/login.html',{'message':message})
    return render(request,'login/login.html')
#通过下面的if语句,我们不允许重复登录:
# if request.session.get('is_login',None):
#     return redirect("/")

# request.session['is_login'] = True
# request.session['user_id'] = user.id
# request.session['user_name'] = user.name

def register(request):
    if request.session.get('is_login',None):
        return redirect('/')
    if request.method == 'POST':
        user = request.POST.get('username')
        password1 = request.POST.get('passwd1')
        password2 = request.POST.get('passwd2')
        email = request.POST.get('email')
        sex = request.POST.get('sex')
        print('user:%s,password1:%s,password2:%s,email:%s,sex:%s'%(user,password1,password2,email,sex))
        if password1 != password2:
            message='两次密码不相同'
            return render(request,'login/register.html')
        else:
            sameuser = models.User.objects.filter(user=user)
            if sameuser:
                message='该用户已经存在'
                return render(request,'login/register.html')
            sameemail =models.User.objects.filter(email=email)
            if sameemail:
                message='该邮箱已经被注册了'
                return render(request,'login/register.html')                
            #django的操作数据库get方法是从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错。
            #django的操作数据库filter方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话,它会返回[]。
            models.User.objects.create(user=user,passwd=password1,email=email,sex=sex)
            new_user = models.User.objects.get(user=user)
            print('用户名称:%s密码:%s'%(new_user.user,new_user.passwd))
            code = make_confirm_string(new_user)
            send_email(email, code)
            #通过make_confirm_string函数获取
            message = '请前往邮箱确认!'
            print('code:%s,message:%s'%(code,message))
            return render(request, 'login/confirm.html',{'message':message})
    return render(request,'login/register.html')

def logout(request):
    if not request.session.get('is_login',None):
        return redirect('/login/')
    request.session.flush()
    return redirect("/login/")

def user_confirm(request):
    code = request.GET.get('code', None)
    message = ''
    try:
        confirm = models.ConfirmString.objects.get(code=code)
    except:
        message = '无效的确认请求!'
        return render(request, 'login/confirm.html', locals())

    c_time = confirm.c_time
    now = datetime.datetime.now()
    print('---now:%s'%(now))
    print('c_time:%s'%(c_time + datetime.timedelta(settings.CONFIRM_DAYS)))
    if str(now) > str(c_time + datetime.timedelta(settings.CONFIRM_DAYS)):
        confirm.user.delete()
        message = '您的邮件已经过期!请重新注册!'
        return render(request, 'login/confirm.html', locals())
    else:
        confirm.user.confiremd = True
        confirm.user.save()
        confirm.delete()
        message = '感谢确认,请使用账户登录!'
        return render(request, 'login/confirm.html', locals())

cat confirm.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册确认</title>
</head>
<body>
    <h1 style="margin-left: 100px;">{{ message }}</h1>
    <script>
        window.setTimeout("window.location='/login/'",2000);
    </script>
</body>
</html>

52018fcd1874e25548e3ea548d1b753946c.jpg

2a9b7b9f818263f1c261e0ea2ecc3a754d1.jpg

eb877725697985947150e631ccad592c151.jpg

d357009ca296154e3ac471e9ae48d999709.jpg

转载于:https://my.oschina.net/wangyunlong/blog/3076447

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值