django学习之包含数据库的登录注册功能

这篇文章实现了简单的登录注册,登录验证,session保存登录状态,cache缓存,ajax接收后台响应,利用{% csrf_token %}防止csrf跨站保护机制。

前端使用html+css+bootstrap+ajax实现,后端使用python django框架,数据库使用mysql数据库。

可以说一个登陆功能,涵盖了基础的django的使用方法。(注销功能还没做,后续会完成)

django的主要目录结构为:setting.py(基本的配置,包括session,缓存,数据库,以及注册你的app等),urls.py(实现url与视图函数的对应),views.py(视图函数,也是逻辑代码的实现地方),manage.py(管理以及启动,python manage.py makemigrations以及python manage.py migrate 来创建或者联系数据库),models.py(数据库模型,与数据库中的表对应)

下面是本人的代码:

views.py
 

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
from  django.shortcuts import HttpResponse,HttpResponseRedirect
from  web_j import models
from django.views.decorators.cache import cache_page

# Create your views here.
#视图函数都在这个py文件里面


def mainweb(request):
    return render(request,"mainweb.html",)
@cache_page(60 * 15) #60秒数,这里指缓存 15 分钟,不直接写900是为了提高可读性
def index(request):
    #return  HttpResponse("hello world!")
    if request.method=="POST":
        username=request.POST.get("username",None)
        password=request.POST.get("password",None)
        if models.user_info.objects.filter(username=username):
            return HttpResponse("insert flase")  #这里通过httpresponse返回给前端信息,前端index.html通过get_insert_response()来提示注册失败信息alert("")
        else:
            models.user_info.objects.create(username=username,userpwd=password) #接收数据保存到数据库,creatr_user用hash值保存
    user_list=models.user_info.objects.all() #从数据库读取所有数据
    return  render(request,"index.html",{"data":user_list}) #第三个参数是后台返回给浏览器的数据,定义data对象,返回一个字典,data会被index.html文件引用

@cache_page(60 * 15)
def login(request):
    if request.method=="POST":
        username = request.POST.get("username", None)
        password = request.POST.get("password", None)
        list_user_pwd = models.user_info.objects.all().values_list('username','userpwd')
        print list_user_pwd
        if list_user_pwd : #取出数据库表中username,userlist两列生成一个列表
            if (username,password) in list_user_pwd :
                request.session['is_login']=True
                request.session['username']=username
                return  HttpResponse("Login successful!")
            else:
                return HttpResponse("用户名不存在,请注册")
        else:
            return  HttpResponse("用户名不存在,请注册")
    return render(request,"login.html",)

def logout(request):
    return '1'
def selfinfo(request):
    if request.session.get('is_login',None)==None:
        print '11111111111'
    else:
        info_name = request.session.get('username',None)
        print info_name
        info_list=models.user_info.objects.all().values_list('username','id')
        print info_list
        info_l={}
        for element in info_list:
            if element[0] == info_name:
                info_l = {'username_info':info_name,
                          'userid_info':element[1]}
        return render(request,"self_info.html",{'user_info':info_l})
    return render(request,"self_info.html"

urls.py 

from django.conf.urls import url
from django.contrib import admin
from web_j import views
#在这里将url与views.py里面的函数对应起来
urlpatterns = [
    #url(r'^admin/', admin.site.urls),
    url(r'index/$',views.index),
    url(r'login/$', views.login),
    url(r'logout/$', views.logout),
    url(r'self_info/',views.selfinfo),
    url(r'',views.mainweb),
]

session.py 

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'web_j',#在这里注册我的app:web_j
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SESSION_COOKIE_AGE = 1209600
ROOT_URLCONF = 'jango_web.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'jango_web.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
      #  'NAME': os.path.join(BASE_DIR, 'db.web'),
        'NAME': 'web',
        'USER':'root',
        'PASSWORD':'123456',
        'HOST':'127.0.0.1',
        'PORT':'3306',
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/' #是引用指针,不是具体目录,不代表目录意义,但在引用静态文件时必须加上这个开头
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)

CACHES={
    'default':{
        'BACKEND':'django.core.cache.backends.locmem.LocMemCache', #这里使用的是在本地内存来进行缓存
    }
}

models.py

from __future__ import unicode_literals

from django.db import models

# Create your models here.
#创建数据库模型表,与数据库中真实的表对应

class user_info(models.Model): #必须继承models.Model类
    id=models.IntegerField(primary_key=True)
    username=models.CharField(max_length=255)
    userpwd=models.CharField(max_length=255)

self_info.html(个人信息介绍页面)

<!doctype html>
<html lang="zh">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>个人信息介绍</title>
   <link rel="stylesheet" type="text/css" href="/static/css/normalize.css" />
   <link rel="stylesheet" type="text/css" href="/static/css/default.css">
   <link href="http://cdn.bootcss.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet">
   <link rel='stylesheet prefetch' href='http://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900'>
   <link rel="stylesheet" type="text/css" href="/static/css/styles.css">

</head>
<body>
   <div class="htmleaf-container">
      <header class="htmleaf-header">
         <h1>个人信息 <span>INFOMATION</span></h1>
         <div class="htmleaf-links">
            <a class="htmleaf-icon icon-htmleaf-home-outline" href="self_info/" title="个人信息" target="_blank"><span> 个人信息</span></a>
            <a class="htmleaf-icon icon-htmleaf-arrow-forward-outline" href="http://localhost:8000/" title="返回主页" target="_blank"><span> 返回主页</span></a>
         </div>
      </header>
      <div class="profile-card-wrap">
         <input id="check" type="checkbox" class="check"><label for="check" class="toggle"> + </label>
         <div class="content" data-text="个人信息">
            <div class="title">欢迎,{{ user_info.username_info }}</div>
            <p>你是第{{ user_info.userid_info }}个注册的用户</p>
         </div>
         <div class="link-info">
            <div class="social">
               <a class="link fb" href="#" target="_blank"><i class="fa fa-facebook"></i></a>
               <a class="link tw" href="#" target="_blank"><i class="fa fa-twitter"></i></a>
               <a class="link cp" href="#" target="_blank"><i class="fa fa-codepen"></i></a>
               <a class="link pi" href="#" target="_blank"><i class="fa fa-weibo"></i></a>
               <a class="link li" href="#" target="_blank"><i class="fa fa-weixin"></i></a>
               <a class="link yt" href="#" target="_blank"><i class="fa fa-qq"></i></a>
               <a class="link gp" href="#" target="_blank"><i class="fa fa-google-plus"></i></a>
            </div>
            <div class="photo"></div>
         </div>
      </div>

   </div>
   
</body>
</html>

mainweb.html(主页面)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link href="/static/css/bootstrap.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="/static/css/index.css">
    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <style type="text/css">
        html, body {width:100%;height:100%;} /*非常重要的样式让背景图片100%适应整个屏幕*/
        .bg {display: table;width: 100%;height: 100%;padding: 100px 0;text-align: center;color: #fff;background: url("/static/img/safari-big.jpg") no-repeat bottom center;background-color: #000;background-size: cover;background-attachment: fixed;}
        .my-navbar {padding:20px 0;transition: background 0.5s ease-in-out, padding 0.5s ease-in-out;}
        .my-navbar a{background:transparent !important;color: #985f0d; !important}
        .my-navbar a:hover {color:#45bcf9 !important;background:transparent;outline:0}
        .my-navbar a {transition: color 0.5s ease-in-out;}/*-webkit-transition ;-moz-transition*/
        .top-nav {padding:0;background:#000000;}
        button.navbar-toggle {background-color:#fbfbfb;}/*整个背景都是transparent透明的,会看不到,所以再次覆盖一下*/
        button.navbar-toggle > span.icon-bar {background-color:#0f0f0f}
    </style>
</head>
<body>
<nav class="navbar navbar-fixed-top my-navbar" role="navigation">
<div class="container-fluid">
    <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#example-navber-collapse">
            <span class="sr-only">切换导航</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="#">部落格</a>
    </div>
    <div class="collapse navbar-collapse" id="example-navbar-collapse">
        <ul class="nav navbar-nav">
            <li class="active"><a href="self_info/">个人信息</a></li>
            <li><a href="login/">登录</a></li>
            <li><a href="index/">注册</a></li>
        </ul>
    </div>
</div>
</nav>

<div class="bg">
</div>
<br /><br /><br /><br /><br /><br /><br /><p><a href="#">XTY所有</a></p>
<script>
    $(window).scroll(function (){
        if ($(".navbar").offset().top > 50 ) {
            $(".navbar-fixed-top").addClass("top-nav");
        }
        else{
            $(".navbar-fixed-top").removeClass("top-nav");
        }
    })
</script>
</body>
</html>

login.html(登录页面)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Login</title>

    <!-- Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link href="/static/css/bootstrap.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="/static/css/index.css">
    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script type="text/javascript">
        function get_login_response() {
            var login_res;
            if (window.XMLHttpRequest) {
                login_res = new XMLHttpRequest();
            }
            else {
                login_res = new ActiveXObject("Microsoft XMLHTTP");
            }
            login_res.onreadystatechange = function () {
                if ((login_res.readyState == 4) && (login_res.status == 200)) {
                    window.alert(login_res.responseText);
                    console.log("login successful");
                }
            }

        }
  </script>
    <style>
        body{
    background: url("/static/img/chrome-logo-small.jpg");
    animation-name:myfirst;
    animation-duration:12s;
    /*变换时间*/
    animation-delay:2s;
    /*动画开始时间*/
    animation-iteration-count:infinite;
    /*下一周期循环播放*/
    animation-play-state:running;
    /*动画开始运行*/
}
@keyframes myfirst
{
    0%   {background:url("/static/img/firefox-logo-small.jpg");}
    34%  {background:url("/static/img/safari-logo-small.jpg");}
    67%  {background:url("/static/img/chrome-logo-small.jpg");}
    100% {background:url("/static/img/bg-white.jpg");}
}
.form{background: rgba(255,255,255,0.2);width:400px;margin:120px auto;}
/*阴影*/
.fa{display: inline-block;top: 27px;left: 6px;position: relative;color: #ccc;}
input[type="text"],input[type="password"]{padding-left:26px;}
.checkbox{padding-left:21px;}
    </style>
</head>

<body>
<div class="container">
    <div class="form row">
        <div class="form-horizontal col-md-offset-3" id="login_form">
            <h1 class="form-title">Login</h1>
            <form action="" method="post">`{% csrf_token %}`
            <div class="col-md-9">
                <div class="form-group">
                    <i class="fa fa-user fa-lg"></i>
                    <input class="form-control required" type="text" placeholder="Username" name="username" autofocus="autofocus" maxlength="20"/>
                </div>
                    <div class="form-group">
                            <i class="fa fa-lock fa-lg"></i>
                            <input class="form-control required" type="password" placeholder="Password" name="password" maxlength="8"/>
                    </div>
                    <div class="form-group">
                        <label class="checkbox">
                            <input type="checkbox" name="remember" value="1"/>记住我
                        </label>
                    </div>
                    <div class="form-group col-md-offset-9">
                        <button type="submit" class="btn btn-success pull-right" name="login_btn" value="Submit" onclick="get_login_response()">登录</button>
                    </div>
            </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>

index.html(注册页面)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link href="/static/css/bootstrap.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="/static/css/index.css">
    <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
    <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
    <!--[if lt IE 9]>
      <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <script>
        function get_insert_response() {
            var inser_re;
            if(window.XMLHttpRequest){
                inser_re=new XMLHttpRequest();
            }
            else{
                inser_re=new ActiveXObject("Microsoft.XMLHTTP");
            }
            inser_re.onreadystatechange=function () {
                if(inser_re.readyState==4 && inser_re.status==200){
                    window.alert(inser_re.responseText);
                }
            }

        }
    </script>

</head>
<body>


</div>
    <h1 >用户输入</h1>
<!-- csrf_token `防止跨站保护机制 -->
<form action="" method="post" >`{% csrf_token %}`
    <p><input type="text" name="username"></p>
    <p><input type="password" name="password"></p>
    <p><input type="submit" value="提交" onclick="get_insert_response()"> </p>
</form>
<h2 >用户展示</h2>
<table border="1">
    <thead>
    <th>用户名</th>
    <th>密码</th>
    </thead>
    <tbody>
    <!-- 这里循环调用index中的data对象 -->
    {% for line in data %}
        <tr>
        <td>{{ line.username }}</td>
        <td>{{ line.userpwd }}</td>
        </tr>

    {% endfor %}

    </tbody>
</table>


</body>
</html>

猜你喜欢

转载自blog.csdn.net/a1496785/article/details/82466514