django學習之包含資料庫的登入註冊功能
阿新 • • 發佈:2018-12-27
本文由本人原創,僅作為自己的學習記錄
這篇文章實現了簡單的登入註冊,登入驗證,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>