上一节,咱们基本了解了 Django 的一些配置,这一节,咱们将经过一个简单的登陆页面,进一步学习 Django 的使用。css
首先,新建一个 Django 项目,记得别弄错了哦。html
这里咱们已经写好了登陆页面(点我下载 密码:abh5),可是这一个登陆页面不单只是一个 HTML 文件,还有一些静态文件。咱们上一次已经说过了,想要在 HTML 中引进静态文件的话,须要在 settings 中配置静态文件夹。login.html 放在 templates 目录下,也须要在 settings 中配置 templates 文件夹。配置完成后以下图。前端
""" Django settings for mysite project. Generated by 'django-admin startproject' using Django 2.0.5. For more information on this file, see https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '-3+5fklj6_ard3d!^66n9=a^6p!v381pvm6r6h=c#84w%nzm1f' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] 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', ] ROOT_URLCONF = 'mysite.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 = 'mysite.wsgi.application' # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/2.0/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/2.0/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/2.0/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
咱们想要浏览器可以找到这一个页面,首先要给它配置一个 url。sql
urls.py 中放的是函数与路径的对应关系。可是函数不该该放在 urls.py 中,应该新建一个 views.py ,专门用来写函数逻辑。django
这里,咱们在 views.py 中定义一个 login 函数,用来收到请求后返回 login.html 页面。要返回一个 HTML 页面,咱们就能够选择导入 render 模块,render 模块能够方便地返回浏览器请求,HTML 页面,还有咱们想要返回的参数。bootstrap
from django.shortcuts import render def login(request): return render(request, 'login.html')
写好逻辑处理函数以后,咱们就来写函数与路径的对应关系,也就是 url 。c#
from django.conf.urls import url from .views import login urlpatterns = [ url(r'^login/$', login), ]
此时的项目目录应该以下图。后端
咱们在 login.html 中经过一个 form 表单,完成用户帐号密码的输入和传送。浏览器
form 表单 action 属性表示输入往哪里送,往哪一个 url 送。method 属性是方法,通常都设置成 post。前端框架
这里,咱们先设置 action="/baobao/" method="post",也就是专门写一个名为 baobao 的函数,用以获取用户提交的数据,作是否登陆成功的判断。
在 baobao 函数中,咱们打印了浏览器 form post 过来的数据,而后返回一个 'O98K' 到页面显示 (#^.^#)
from django.conf.urls import url from .views import login, baobao urlpatterns = [ url(r'^login/$', login), url(r'^baobao/$', baobao), ]
from django.shortcuts import render, HttpResponse def login(request): return render(request, 'login.html') def baobao(request): # 获取用户提交的数据,作是否登陆成功的判断 email = request.POST print(request.POST) return HttpResponse('O98K')
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css"> <title>mysite-登陆页面</title> <style> body { background-color: #eee; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-4 col-md-offset-4" style="margin-top: 100px"> <h1 class="text-center">请登陆</h1> <form class="form-horizontal" action="/login/" method="post"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label"></label> <div class="input-group col-sm-8"> <span class="input-group-addon"><i class="fa fa-envelope-o fa-fw"></i></span> <input type="email" name="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label"></label> <div class="input-group col-sm-8"> <span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span> <input type="password" name="pwd" class="form-control" id="inputPassword3" placeholder="Password"> </div> </div> <div class="form-group"> <div class="input-group col-sm-offset-2 col-sm-8"> <div class="checkbox"> <label> <input type="checkbox"> 记住我 </label> </div> </div> </div> <div class="form-group"> <div class="input-group col-sm-offset-2 col-sm-8"> <button type="submit" class="btn btn-primary btn-block">登陆</button> </div> </div> </form> </div> </div> </div> </body> </html>
启动项目,在浏览器输入 http://127.0.0.1:8000/login/,回车,顺利出现了咱们的登陆页面。
一脸兴奋,输入随便一个邮箱、密码,点击登陆。什么?怎么提示错误了!!!
你肯定你输入的是邮箱地址吗(*/ω\*).....
这一个提示,是 bootstrap 前端框架帮咱们作的,在前端就进行了一次简单的表单验证。boostrap 是什么?你如今姑且把它当成是一个前端框架,咱们之后再讲。
再一次,输入正确的邮箱地址,密码,点击登陆。Forbidden?这是什么鬼???
能够看到,url 已经成功跳转到 baobao 了,不过页面却显示 Forbidden。下面还有一行 CSRF verification failed. Request aborted. 这一个是 Django 自带的 CSRF 防范机制。CSRF 是什么?某度百科有言:“CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,一般缩写为CSRF或者XSRF,是一种对网站的恶意利用。”(能够看出,咱们的 Django 框架,但是至关的严谨和方便。)
那么,这里咱们应该怎么作呢?咱们只须要在 form 表单标签内部加上一句 {% csrf_token %} 便可。
此时的 login.html 应为
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css"> <title>mysite-登陆页面</title> <style> body { background-color: #eee; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-4 col-md-offset-4" style="margin-top: 100px"> <h1 class="text-center">请登陆</h1> <form class="form-horizontal" action="/login/" method="post"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label"></label> <div class="input-group col-sm-8"> <span class="input-group-addon"><i class="fa fa-envelope-o fa-fw"></i></span> <input type="email" name="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label"></label> <div class="input-group col-sm-8"> <span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span> <input type="password" name="pwd" class="form-control" id="inputPassword3" placeholder="Password"> </div> </div> <div class="form-group"> <div class="input-group col-sm-offset-2 col-sm-8"> <div class="checkbox"> <label> <input type="checkbox"> 记住我 </label> </div> </div> </div> <div class="form-group"> <div class="input-group col-sm-offset-2 col-sm-8"> <button type="submit" class="btn btn-primary btn-block">登陆</button> </div> </div> {% csrf_token %} </form> </div> </div> </div> </body> </html>
重启项目,再次回到 login 页面,输入,登陆。终于看到咱们想要的 ‘O98K’ 了。 o(╥﹏╥)o
并且能够在 pycharm 的 Terminal 中看到打印出来的数据。(我是在 pycharm 的 Terminal 中启动项目的,因此能够在这里看到打印的数据)
'email' 对应的是咱们输入的邮箱。'pwd' 对应的是咱们输入的密码。'email' 和 'pwd' 是在哪里定义的呢?是咱们在 login.html 的 form 的 input 中定义的 name 属性。要想给服务器传数据,必须给它们起一个 name。
既然能够获取到浏览器传过来的数据了,咱们就能够在 baobao 函数中取出这些数据,作邮箱、密码的验证。
from django.shortcuts import render, HttpResponse def login(request): return render(request, 'login.html') def baobao(request): # 获取用户提交的数据,作是否登陆成功的判断分别 # 取出邮箱和密码进行验证 email = request.POST.get('email', None) pwd = request.POST.get('pwd', None) if email == '123@qq.com' and pwd == 'abc123': # 登陆成功 return HttpResponse('登陆成功') else: # 登陆失败 return HttpResponse('登陆失败')
输入错误的邮箱和密码进行登陆,再输入正确的邮箱和密码进行登陆。能够看到,咱们想要的逻辑都可以正确运行。
整理一下逻辑
首先,启动项目以后,在浏览器输入 http://127.0.0.1:8000/login/,浏览器就会给服务器发送一个 GET 请求,服务器给浏览器返回 login 页面。当用户填完登陆表单点击登陆的时候,浏览器就会向服务器发送一个 POST 请求,给服务器提交数据。服务器收到浏览器提交过来的数据(邮箱、密码),在逻辑函数中进行验证,并给浏览器返回相应的结果。
到这里,不知道你是否发现,咱们的逻辑函数和 url 设置太过累赘。明明是一个登陆功能,却写了两个页面,用两个函数进行处理。下面,咱们将对代码进行改进。把返回 login 页面和 邮箱密码验证 功能都写进 login 函数中。
from django.shortcuts import render, HttpResponse def login(request): if request.method == 'POST': # 获取用户提交的数据,作是否登陆成功的判断分别 # 取出邮箱和密码进行验证 email = request.POST.get('email', None) pwd = request.POST.get('pwd', None) if email == '123@qq.com' and pwd == 'abc123': # 登陆成功 return HttpResponse('登陆成功') else: # 登陆失败 return HttpResponse('登陆失败') # 若是不是POST,就返回login页面 return render(request, 'login.html')
相应的,login.html 中 form 的 action 也要改变成 login,urls.py 和 views.py 中的 baobao 相关能够删除。
登陆测试,发现能够正常运行,并且 url 一直都是 login。
什么?你说这样太丑了???
对,这样的登陆功能实在是太丑了,通常的登陆失败以后都不会跳转到另外一个页面说你登陆失败,而是在输入邮箱和密码的页面就提示登陆失败了。
好的,那咱们就动手改一下吧。要想错误信息显示在登陆界面,就是说须要后端返回一个值到前端来。咱们在 login 函数里面整理逻辑,在函数一开始的时候,就先给它一个空的错误信息,若是浏览器传过来的是 POST 方法,而且帐号密码不正确,那么错误信息 error_msg 就是 ‘帐号或密码错误’。而后再经过 render 模块返回浏览器。
from django.shortcuts import render, HttpResponse def login(request): error_msg = '' if request.method == 'POST': # 获取用户提交的数据,作是否登陆成功的判断分别 # 取出邮箱和密码进行验证 email = request.POST.get('email', None) pwd = request.POST.get('pwd', None) if email == '123@qq.com' and pwd == 'abc123': # 登陆成功 return HttpResponse('登陆成功') else: # 登陆失败 error_msg = '帐号或密码错误' # 若是不是POST,就返回login页面 return render(request, 'login.html', {'error': error_msg})
同时,login.html 也须要提取后端传过来的 error_msg ,并显示在登陆页面上,相应的代码以下。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css"> <title>mysite-登陆页面</title> <style> body { background-color: #eee; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-4 col-md-offset-4" style="margin-top: 100px"> <h1 class="text-center">请登陆</h1> <form class="form-horizontal" action="/login/" method="post"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label"></label> <div class="input-group col-sm-8"> <span class="input-group-addon"><i class="fa fa-envelope-o fa-fw"></i></span> <input type="email" name="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label"></label> <div class="input-group col-sm-8"> <span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span> <input type="password" name="pwd" class="form-control" id="inputPassword3" placeholder="Password"> </div> </div> <div class="form-group"> <div class="input-group col-sm-offset-2 col-sm-8"> <div class="checkbox"> <label> <input type="checkbox"> 记住我 </label> </div> </div> </div> <div class="form-group"> <div class="input-group col-sm-offset-2 col-sm-8"> <button type="submit" class="btn btn-primary btn-block">登陆</button> </div> <p class="text-danger text-center">{{ error }}</p> </div> {% csrf_token %} </form> </div> </div> </div> </body> </html>
测试登陆功能,一切正常,登录成功跳转页面并显示“登陆成功”,登陆失败直接在表单下显示错误信息。
你可能会疑惑,刚才咱们在 login.html 中加的一句 {{ error }} 是什么意思啊?没见过啊?
这个,是 Django 自带的模板语言。不知道你是否还记得,在以前讲动态页面的时候,用 “@@xx@@”做为占位符,并在后端经过字符串替换的方法,把“@@xx@@”换成了当前时间。同理,这里的 {{ error }} 也相似于一个占位符,不过这里就不须要咱们写函数去更改了,只要咱们把同名的参与以字典的形式传给前端页面,Django 就会自动帮咱们替换。
固然,你也能够在登陆成功以后,跳转到其余的网页去,例如你本身的博客。
这里就会用到一个新的函数 重定向 redirect。redirect 的做用,回复一个特殊的响应,这个响应会让用户浏览器请求指定的URL。
from django.shortcuts import render, HttpResponse, redirect def login(request): error_msg = '' if request.method == 'POST': # 获取用户提交的数据,作是否登陆成功的判断分别 # 取出邮箱和密码进行验证 email = request.POST.get('email', None) pwd = request.POST.get('pwd', None) if email == '123@qq.com' and pwd == 'abc123': # 登陆成功 # 回复一个特殊的响应,这个响应会让用户浏览器请求指定的URL return redirect('http://www.cnblogs.com/chuangming/') else: # 登陆失败 error_msg = '帐号或密码错误' # 若是不是POST,就返回login页面 return render(request, 'login.html', {'error': error_msg})
这一次,咱们回顾了项目的新建、settings 中静态文件、templates 路径配置,对项目逻辑和 url 进行规划和优化,接触到了 form 表单的使用,而且初次涉猎到 CSRF 和 Django 的模板语言,还有重定义函数 redirect。
你会发现,咱们如今只弄了一个登陆界面,就搞了这么多的逻辑,可是一个项目不是仅仅由一个登陆页面构成的,它还会有其余的功能,登陆只是它的一小部分。那么这样子的话,咱们须要对其功能进行划分,分红一个个 APP,这样更便于管理。至于什么是 APP,咱们下一节再讲,谢谢你们!(#^.^#)