Django项目-个人网站之登录注册模块

Django项目之个人网站

Github地址:https://github.com/liangdongchang/MyWeb.git

感兴趣的可以fork或star一下
这里写图片描述

功能模块一:登录/注册

一、说明

功能:用户名、密码、验证码输入、头像上传

技术:文件上传、验证码、密码加密、会话技术

二、界面
1、登录

这里写图片描述

2、注册

这里写图片描述

三、代码
1、前端(T)
1.1 base.html
{#    父模板base.html#}
{% load static %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
{#    响应式web设计,自适应浏览器大小#}
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="save" content="history">

    {% block title %}
         <title>首页</title>
    {% endblock %}
    {% block link %}
    {% endblock %}

    <link href="{% static 'SitesApp/css/reset.css' %}" rel="stylesheet">
    <link href="{% static 'SitesApp/css/sitesAppCss.css' %}" rel="stylesheet">
{#    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">#}
{#    <script src="https://cdn.bootcss.com/jquery/1.12.0/jquery.min.js"></script>#}
{#    <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>#}
   <link href="/static/SitesApp/css/bootstrap.min.css" rel="stylesheet">
    {% block style %}

    {% endblock %}
    <script src="/static/SitesApp/js/jquery.min.js"></script>
    <script src="/static/SitesApp/js/bootstrap.min.js"></script>

    {% block script %}
         <script type="text/javascript"></script>
    {% endblock %}

</head>
<body style="background-color: #E6E6FA;">
<a href="{% url 'sitesApp:vote' 1 %}">hhhhh</a>
<div class="box">
    <div class="header">

        <ul class="nav nav-pills navbar faq-tabbable">
            <li role="presentation" class="active"><a href="{% url 'sitesApp:home' %}">首页</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:vote' 1 %}">投票</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:grade' %}">打分</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:review' %}">回顾</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:blog' %}">博客</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:dataBank' %}">资料</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:forum' %}">论坛</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:mine' %}">我的</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:login' %}">登录</a></li>
            <li role="presentation"><a href="{% url 'sitesApp:register' %}">注册</a></li>

        </ul>
    </div>
    <div class="time" >
         <span id="mytime"></span>
    </div>
    <div class="content" style="position: relative;">
        {% block content %}
            这家伙很懒,还没开始开发...~_~
        {% endblock %}

    </div>
    <div class="footer">
        {% block footer %}
            开发者 LDC
        {% endblock %}

    </div>
</div>
<script type="text/javascript">
    $(function ($) {
    {#    导航栏按钮渲染#}
      $(".faq-tabbable").find("li").each(function () {
        var a = $(this).find("a:first")[0];
         if ($(a).attr("href") === location.pathname) {
          $(this).addClass("active");
        } else {
           $(this).removeClass("active");
        }
      });
    });
    {#实时显示时间#}
    function showTime(){
            nowtime=new Date();
            year=nowtime.getFullYear();
            month=nowtime.getMonth()+1;
            date=nowtime.getDate();
            document.getElementById("mytime").innerText=year+"年"+month+"月"+date+" "+nowtime.toLocaleTimeString();
        }

        <!--定时刷新时间-->
        setInterval("showTime()",1000);
</script>

</body>
</html>
1.2 login.html
{% extends 'SitesApp/base.html' %}

{% block title %}
    <title>登录</title>
{% endblock %}
{% block content %}
    {#   文件上传、验证码、密码加密、会话技术#}
    <form id="formLogin" method="post" action="{% url 'sitesApp:login' %}"
          onkeydown="if(event.keyCode==13) return focusNextInput(this);">
        {% csrf_token %}
        <div class="login">
            <div class="input-group">
                <span class="input-group-addon" id="basic-addon1">用户名</span>
                <input type="text" class="form-control" placeholder="Username" aria-describedby="basic-addon1"
                       name="uname" onkeyup="if(event.keyCode==13) focusNextInput(this);">
            </div>

            <div class="input-group">
                <span class="input-group-addon" id="basic-addon1">密&nbsp;&nbsp;&nbsp;&nbsp;码</span>
                <input type="password" class="form-control" placeholder="Password" aria-describedby="basic-addon1"
                       name="upwd" onkeyup="if(event.keyCode==13) focusNextInput(this);">
            </div>
            <div class="input-group">
                <span class="input-group-addon" id="basic-addon1">验证码</span>
                <input type="text" class="form-control" placeholder="Auth code" aria-describedby="basic-addon1"
                       name="vcode" onkeyup="if(event.keyCode==13) focusNextInput(this);">
            </div>
            <div class="vcode">
                <img src="/app/getvcode/" id="vcode">
            </div>
            <input id="submit" type="submit" class="loginBtn" value="登  录">
        </div>
    </form>
{% endblock %}
{% block script %}
    <script src="/static/SitesApp/js/jquery-form.js"></script>
    <script type="text/javascript">
        $(function () {
            {#            验证码点击时生成随机的路由请求#}
            $('#vcode').click(function () {
                $(this).attr('src', "/app/getvcode" + Math.random())
            })
        });
        {#        表单提交后,处理服务器返回的数据#}
        $(document).ready(function () {
            $("#formLogin").ajaxForm(function (data) {
                {#                 alert("post success." + data);#}
                data = $.parseJSON(data);
                if (data['status'] == '1') {
                    {#                        alert('登录成功');#}
                    {#          跳转到我的主页           #}
                    window.location.href = "{% url 'sitesApp:mine' %}";
                } else {
                    alert(data['ret']);
                }
            });
        });
        //jQuery实现在一个输入框按回车键后光标跳到下一个输入框
        function focusNextInput(thisInput) {
            var inputs = document.getElementsByTagName("input");
            for (var i = 0; i < inputs.length; i++) {
                // 如果是最后一个,则焦点回到第一个
                if (i == (inputs.length - 1)) {
                    inputs[0].focus();
                    break;
                } else if (thisInput == inputs[i]) {
                    inputs[i + 1].focus();
                    break;
                }
            }
            return false;
        }
    </script>
{% endblock %}
1.3 register.html
{% extends 'SitesApp/base.html' %}

{% block title %}
    <title>注册</title>
{% endblock %}
{% block content %}
    {#   文件上传、验证码、密码加密、会话技术#}
    {# enctype="multipart/form-data" 上传支持 #}
    <form id="formLogin" method="post" action="{% url 'sitesApp:register' %}" enctype="multipart/form-data">
        {% csrf_token %}
        <div class="login" style="height: 380px">
            <div class="input-group">
                <span class="input-group-addon" id="basic-addon1">用户名</span>
                <input type="text" class="form-control" placeholder="Username" aria-describedby="basic-addon1"
                       id="uname" name="uname" >
            </div>
            <div class="input-group">
                <span class="input-group-addon" id="basic-addon1">昵&nbsp;&nbsp;&nbsp;&nbsp;称</span>
                <input type="text" class="form-control" placeholder="Nickname" aria-describedby="basic-addon1"
                       id="unick" name="unick" >
            </div>
            <div class="input-group">
                <span class="input-group-addon" id="basic-addon1">密&nbsp;&nbsp;&nbsp;&nbsp;码</span>
                <input type="password" class="form-control" placeholder="Password" aria-describedby="basic-addon1"
                       id="upwd" name="upwd" >
            </div>
            <div class="input-group">
                {# 用于上传头像的表单控件 #}
                <span class="input-group-addon" id="basic-addon1">头&nbsp;&nbsp;&nbsp;&nbsp;像</span>
                <input type="file" class="form-control" aria-describedby="basic-addon1" style="height: 37px;"
                       id="uicon" name="uicon" onchange="check()">
            </div>
            <div class="input-group">
                <span class="input-group-addon" id="basic-addon1">验证码</span>
                <input type="text" class="form-control" placeholder="Auth code" aria-describedby="basic-addon1"
                       id="vcod" name="vcode" onchange="check()">
            </div>
            <div class="vcode" style="margin: 0;height: 65px;">
                <img src="/app/getvcode/" id="vcode">
            </div>
            <input type="submit" class="loginBtn" value="注  册">
        </div>
    </form>

{% endblock %}
{% block script %}
    <script src="/static/SitesApp/js/jquery-form.js"></script>
    <script type="text/javascript">
        {#    验证码点击事件    #}
        $(function () {
            $('#vcode').click(function () {
                $(this).attr('src', "/app/getvcode" + Math.random())
            });

        });
        {#        表单数据提交后对服务器返回的数据进行处理#}
        $(document).ready(function () {
            $("#formLogin").ajaxForm(function (data) {
                {#                 alert("post success." + data['status']);#}
                if (data['status'] == '1') {
                    alert('注册成功');
                    window.location.href = "{% url 'sitesApp:login' %}";
                } else {
                    alert("注册失败,请检查输入信息!!!");
                }
            });
        });
        {#        检查上传的文件是否为图片#}
        function check() {
            var icon = document.getElementById("icon").value.toLowerCase().split('.');//以“.”分隔上传文件字符串

            if (icon[icon.length - 1] == 'gif' || icon[icon.length - 1] == 'jpg' || icon[icon.length - 1] == 'bmp'
                || icon[icon.length - 1] == 'png' || icon[icon.length - 1] == 'jpeg')//判断图片格式
            {
                var imagSize = document.getElementById("icon").files[0].size;
                {#                alert("图片大小:" + imagSize + "B");#}
                if (imagSize < 1024 * 1024 * 3) {
                    return true;
                }
                alert("图片大小在3M以内,您选中的图片大小为:" + (imagSize / (1024 * 1024)).toFixed(2) + "M");

            }
            else {
                alert('请选择格式为*.jpg、*.gif、*.bmp、*.png、*.jpeg 的图片');
            }
            {#                文件选择错就把原文件清空#}
            var obj = document.getElementById('icon');
            obj.outerHTML = obj.outerHTML;
        }
    </script>
{% endblock %}
2 路由处理(V)
2.1 项目下的总路由
urlpatterns = [
    url('^app/',include('SitesApp.urls',namespace='sitesApp'))
]
2.2 子应用下的路由
    # 登录
    url(r'^login/', views.login, name='login'),
    # 注册
    url(r'^register/', views.register, name='register'),
3、视图函数处理(Views)
3.1 登录
# 登录
def login(request):
    if request.method == 'GET':
        return render(request, 'SitesApp/login.html')
    else:
        # 预定义一个最终返回的Response对象(可以动态地为其配置内容,要想勒令客户端做事情必须要有一个Response对象)
        resp = HttpResponse()
        respData = {'status': '0', 'ret': '登录失败,输入信息有误!!!'}
        # 获取用户输入的用户名、密码、验证码
        uname = request.POST.get('uname', None)
        upwd = request.POST.get('upwd', None)
        vcode = request.POST.get('vcode', None)
        # 校验验证码
        # 从session中获取正确的验证码
        sessVcode = request.session.get('vcode', None)
        # 比较用户输入的验证码与正确的验证码是否匹配
        # 事先全部转换为小写形式,这样用户可以忽略大小写
        if vcode and sessVcode and vcode.lower() == sessVcode.lower():
            # 对密码做消息摘要
            upwd = useMd5(upwd)
            # 查询名称为uname的用户
            user = User.uManager.filter(uName=uname).first()
            if not user:
                respData = {'status': '0', 'ret': '用户不存在!!!'}
            # 检查密码、验证码是否匹配
            if user and upwd == user.uPwd :
                # # 勒令客户端(通过cookie)自己将状态保存起来,过期时间为60秒
                # resp.set_cookie('uname',uname,max_age=60*1)

                # # 让服务端通过session保存用户状态
                # 向客户端端要session其实是要存储在cookie中的sessionid
                # request.session的言下之意是"request.getSessionBySessionid"
                # request.session['uname'] = uname
                # request.session['upwd'] = upwd

                '''
                token相当于手动实现的session
                session将用户状态保存在django_session的表中
                token将用户状态保存在何处完全取决于程序媛自己,例如:User表
                但务必使保存用户状态的这张表中有用于作为[id/key/信物]的字段(该字段必须唯一),例如:utoken
                和session一样,必须在客户端的cookie中存一个相同的[id/key/信物],例如:utoken
                如何获取存储的用户状态:先从cookie中拿出utoken,进而查询User表中utoken为xxx的记录,就可以拿到uname了
                '''
                # 将用户状态保存在token中,让客户端持有一个token,将该token保存在某个表中
                # 生成令牌/信物
                token = str(uuid.uuid4())
                # 将该令牌/信物存储在客户端的cookie中,过期时间一天
                resp.set_cookie('utoken', token,expires=60*60*24)
                # 将同样的信物存一份在服务端的表中
                user.uToken = token
                try:
                    user.save()
                    respData = {'status': '1', 'ret': 'login success!'}
                except BaseException as e:
                    print(e)
                    respData = {'status': '0', 'ret': '登录失败,输入信息有误!!!'}
                pass
        resp.content = json.dumps(respData)
        return resp
3.2 注册
# 注册
def register(request):
    if request.method == 'GET':
        return render(request, 'SitesApp/register.html')
    else:
        # 获取用户输入的用户名、昵称、密码、验证码、上传的头像
        uname = request.POST.get('uname', None)
        unick = request.POST.get('unick', None)
        upwd = request.POST.get('upwd', None)
        vcode = request.POST.get('vcode', None)
        uip = getUserIP(request)
        # 拿到用户上传的文件数据,类型是框架类InMemoryUploadedFile
        uiconFile = request.FILES.get('uicon', None)
        # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
        print(uname,unick, upwd, vcode, uiconFile, type(uiconFile))

        # 手动存储上传的文件
        # 自定义文件位置
        # if uiconFile:
        #   fp = os.path.join(MEDIA_ROOT, 'x-' + uiconFile.name)
        #   # 写入文件
        #   with open(fp, 'wb') as file:
        #       # 逐"桶"读取上传的文件数据,并写入本地文件
        #       for buffer in uiconFile.chunks():
        #           file.write(buffer)

        # 校验验证码
        # 从session中获取正确的验证码
        sessVcode = request.session.get('vcode', None)
        # 比较用户输入的验证码与正确的验证码是否匹配
        # 事先全部转换为小写形式,这样用户可以忽略大小写
        if vcode and sessVcode and vcode.lower() == sessVcode.lower():
            user = User()
            user.uName = uname
            user.uNickName = unick
            user.uIP = uip
            # 对密码做消息摘要(目的是避免明文存储)
            user.uPwd = useMd5(upwd)

            # 将上传过来的文件直接赋值给用户的ImageField字段uicon
            # 框架会自动将图片存储在MEDIA_ROOT中
            if uiconFile:
                user.uIcon = uiconFile
            # 把数据写进数据库
            try:
                user.save()
                return JsonResponse({'status': 1, 'ret': 'register success!'})
            except BaseException as e:
                print(e)

        return JsonResponse({'status':0,'ret':'输入信息有误!'})

猜你喜欢

转载自blog.csdn.net/lm_is_dc/article/details/80655225