django学习3 - 视图

学习的书《Web接口开发与自动化测试 基于Python语言》,跟着一起做一个发布会签到系统。

#登录系统,修改demo/hello/templates/index.html文件,修改如下:

<html>
    <head>
        <title>Django Page</title>
    </head>
    <body>
        <h1>发布会管理</h1>
        <form>
            <input name="username" type ="text" placeholder="username"><br>
            <input name="password" type ="password" placeholder="password"><br>
            <button id="btn" type = "submit">登录</button>
        </form>
    </body>
</html>

浏览器访问
在这里插入图片描述
虽然呈现登录界面,但还是不可用。还需要思考输入信息后,点击登录按钮,表单的数据将以什么样的方式(GET/POST)提交到服务端?如何验证用户名密码的有效性?验证成功如何处理?验证失败如何处理?

##- GET:从指定资源获取数据。
修改demo/hello/templates/index.html 中 ,浏览器重新刷新。输入用户名和密码后,点击登录。
在这里插入图片描述
我们看看GET如何传递参数 http://127.0.0.1:8000/index/?username=hangzhou&password=123456
GET 方法会将用户提交的参数添加到URL地址后面,路径后跟“?”号。username为HTML中标签的name属性(username=hangzhou),hangzhou是填入的值;password=123456取值方式一样。多个参数之间用“&”符号隔开。

##- POST:向指定资源提交要被处理的数据。
修改demo/hello/templates/index.html 中 ,浏览器重新刷新。输入用户名和密码后,点击登录。

在这里插入图片描述
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
Django针对CSRF的保护措施是在生成每个表单中放置一个自动生成的令牌,通过令牌来判断POST请求是不是同一个网站。
修改demo/hello/templates/index.html文件,使用模板标签,增加 {% csrf_token %} ,修改如下:

<html>
    <head>
        <title>Django Page</title>
    </head>
    <body>
        <h1>发布会管理</h1>
        <form method="POST">
            <input name="username" type ="text" placeholder="username"><br>
            <input name="password" type ="password" placeholder="password"><br>
            <button id="btn" type = "submit">登录</button>
            {% csrf_token %}
        </form>
    </body>
</html>

浏览器按F12启动开发者工具,输入用户名和密码后,点击登录。
在这里插入图片描述
可以观察到POST页面有username和password两个参数,还有一个csrfmiddlewaretoken的参数,值为当前会话ID加上一个密钥的散列值。

##处理登录请求
可以通过form表单的action属性来指定数据提交的路径,修改demo/hello/templates/index.html

当填写用户名密码,点击“登录”按钮时,由http://127.0.0.1:8000/login_action/路径来提交登录请求,所以要在url.py文件里添加login_action路由请求。

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('login_action/',views.login_action),
]

再由视图views.py的login_action函数来处理登录行为,添加login_action函数

def login_action(request):
    if request.method =='POST': #确认是否为POST方法
        username = request.POST.get('username','') #获取用户名
        password = request.POST.get('password','') #获取密码
        if username == 'admin' and password =='123456':  #如果用户名和密码都匹配
            return HttpResponse("login success!")	#返回登录成功字符串
        else:
            return render(request,"index.html",{'error':'用户名或密码错误!'}) #如果失败,返回错误信息。

修改模板index.html文件,添加{{error}}
,它对应视图文件里render返回字典的key,即{‘error’:‘用户名或密码错误!’}的error,index.html会取error的值,就是’用户名或密码错误!’。

<html>
    <head>
        <title>Django Page</title>
    </head>
    <body>
        <h1>发布会管理</h1>
        <form method='POST' action='/login_action/'>
            <input name="username" type ="text" placeholder="username"><br>
            <input name="password" type ="password" placeholder="password"><br>
            {{error}}<br>
            <button id="btn" type = "submit">登录</button>
            {% csrf_token %}
        </form>
    </body>
</html>

下面是页面输入正确用户名和密码
在这里插入图片描述

在这里插入图片描述
页面输入错误用户名和密码

##登录成功页
现在登录成功后只是HttpResponse(“login success!”),返回"login success!"的字符串,修改成html页面来处理。

在templates目录下创建event_manage.html的文件

<html>
    <head>
        <title>Event Manage Page</title>
    </head>
    <body>
        <h1>Login Success!!!</h1>
    </body>
</html>

修改视图views.py文件如下:

from django.shortcuts import render
from django.shortcuts import HttpResponse,HttpResponseRedirect #新导入HttpResponseRedirect 类
# Create your views here.
def index(request):
    #return HttpResponse("Hello Django!")
    return render(request,"index.html")

def login_action(request):
    if request.method =='POST':
        username = request.POST.get('username','')
        password = request.POST.get('password','')
        if username == 'admin' and password =='123456':
            #return HttpResponse("login success!") 
            return HttpResponseRedirect('/event_manage/') #HttpResponseRedirect类将路径重定义,指向event_manage
        else:
            return render(request,"index.html",{'error':'用户名或密码错误!'})

def event_manage(request): #event_manage函数
    return render(request,"event_manage.html") #渲染event_manage.html文件

需要在urls.py路由配置文件中

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('login_action/',views.login_action),
    path('event_manage/',views.event_manage), #event_manage路径指向,视图里event_manage函数
]

##Cookie
Cookie 在网络系统中几乎无处不在,当我们浏览以前访问过的网站时,网页中可能会出现 :你好 XXX,这会让我们感觉很亲切,就好像吃了一个小甜品一样。这其实是通过访问主机中的一个文件来实现的,这个文件就是 Cookie。在 Internet 中,Cookie 实际上是指小量信息,是由 Web 服务器创建的,将信息存储在用户计算机上的文件。一般网络用户习惯用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 Session 跟踪而存储在用户本地终端上的数据,而这些数据通常会经过加密处理。
Cookie 在计算机中是个存储在浏览器目录中的文本文件,当浏览器运行时,存储在 RAM 中发挥作用 (此种 Cookies 称作 Session Cookies),一旦用户从该网站或服务器退出,Cookie 可存储在用户本地的硬盘上 (此种 Cookies 称作 Persistent Cookies)。
通常情况下,当用户结束浏览器会话时,系统将终止所有的 Cookie。当 Web 服务器创建了Cookies 后,只要在其有效期内,当用户访问同一个 Web 服务器时,浏览器首先要检查本地的Cookies,并将其原样发送给 Web 服务器。这种状态信息称作“Persistent Client State HTTP Cookie” ,简称为 Cookies。

修改视图views.py文件如下:

from django.shortcuts import render
from django.shortcuts import HttpResponse,HttpResponseRedirect
# Create your views here.
def index(request):
    #return HttpResponse("Hello Django!")
    return render(request,"index.html")

def login_action(request):
    if request.method =='POST':
        username = request.POST.get('username','')
        password = request.POST.get('password','')
        if username == 'admin' and password =='123456':
            #return HttpResponse("login success!")
            response = HttpResponseRedirect('/event_manage/')
            response.set_cookie('user',username,3600) #添加浏览器Cookie
            #set_cookie()方法传了三个参数:第一个参数“user”表示写入浏览器Cookie名;
            #第二个参数username表示用户输入的用户名;第三个参数3600是设置Cookie信息在浏览器中的保存时间,单位是秒。
            return response
        else:
            return render(request,"index.html",{'error':'用户名或密码错误!'})

def event_manage(request):
    username = request.COOKIES.get('user','')  #request.COOKIES读取浏览器Cookie名为“user”的值
    return render(request,"event_manage.html",{"user":username}) #将username传递到event_manage.html

修改event_manage.html文件

<html>
    <head>
        <title>Event Manage Page</title>
    </head>
    <body>
        <h1>Login Success!!!</h1>
        <div style="float:right;">
            <a>嘿! {{ user }} 欢迎</a><hr/>
        </div>
    </body>
</html>

登录输入用户名:admin 密码:123456,登录页显示Cookie里的用户名。
按F12使用开发者调试工具,查看存储->Cookie里多了user的变量,值是admin。

在这里插入图片描述
实际上,Cookie中保存的用户名、密码等个人敏感信息通常经过加密,很难将其反向破解。但这并不意味着绝对安全,黑客可通过木马病毒盗取用户浏览器Cookie,直接通过偷取的Cookie骗取网站信任。可以看出,木马病毒入侵用户电脑是导致用户个人信息泄露的一大元凶。
自1993年Cookie诞生以来,其就拥有专属性原则,即A网站存放在Cookie中的用户信息,B网站是没有权限直接获取的。但是,一些第三方广告联盟的代码使用范围很广。这就造成用户在A网站搜索了一个关键字,用户继续访问B网站,由于B网站也使用了同一家的第三方广告代码,这个代码可以从Cookie中获取用户在A网站的搜索行为,进而展示更精准的推广广告。比如搜索“糖尿病”等关键词,再访问其联盟网站,页面会立刻出现糖尿病治疗广告。如果并未事先告之,经用户同意,此做法有对隐私构成侵犯的嫌疑。这个还处在灰色地带。

##Session 相比Cookie安全很多

from django.shortcuts import render
from django.shortcuts import HttpResponse,HttpResponseRedirect
# Create your views here.
def index(request):
    #return HttpResponse("Hello Django!")
    return render(request,"index.html")

def login_action(request):
    if request.method =='POST':
        username = request.POST.get('username','')
        password = request.POST.get('password','')
        if username == 'admin' and password =='123456':
            #return HttpResponse("login success!")
            response = HttpResponseRedirect('/event_manage/')
            #response.set_cookie('user',username,3600) #添加浏览器cookie
            request.session['user']=username #将session信息记录到浏览器
            return response
        else:
            return render(request,"index.html",{'error':'用户名或密码错误!'})

def event_manage(request):
    #username = request.COOKIES.get('user','') #读取浏览器cookie
    username = request.session.get('user','') #获取浏览器session
    return render(request,"event_manage.html",{"user":username}) #将username传递到event_manage.html

登录输入用户名:admin 密码:123456,点击登录,出现“no such table: django_session”报错
在这里插入图片描述
Web服务器端需要用数据库保存session数据,Django已经默认安装SQLite3 ,需要创建django_sessionbi数据库表。

(base) C:\python\django\demo>python manage.py migrate #创建表
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK

重启Django应用
(base) C:\python\django\demo>python manage.py runserver
登录输入用户名:admin 密码:123456,点击登录。浏览器Cookie中多了一个sessionid的参数。
在这里插入图片描述
##Django认证系统
目前为止,虽然实现登录功能,但用户登录信息的验证是有问题的。目前的做法只是简单用if语句判断username和password是否为固定值,下面用Django的认证系统来实现真正的用户信息验证。

Django在使用“python manage.py migrate”数据迁移时,Django同时也生成auth_user表,该表的用户可以来登录Django自带的Admin管理后台。先创建登录Admin后台的管理员账号。
(base) C:\python\django\demo>python manage.py createsuperuser
Username (leave blank to use ‘jing’): admin
Email address: admin@mail.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
This password is too common.
This password is entirely numeric.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

创建的用户名和密码是:admin/123456,浏览器访问http://127.0.0.1:8000/admin/,输入用户名和密码。

##引用Django认证登录
Django已经封装好用户认证和登录的相关方法,我们可以直接调用,同样用auth_user表中的数据进行验证,就是刚才创建的用户名和密码。

修改login_action函数

from django.shortcuts import render
from django.shortcuts import HttpResponse,HttpResponseRedirect
from django.contrib import auth

# Create your views here.
def index(request):
    #return HttpResponse("Hello Django!")
    return render(request,"index.html")

def login_action(request):
    if request.method =='POST':
        username = request.POST.get('username','')
        password = request.POST.get('password','')
        #使用authenticate()函数认证给出的用户名和密码。用户名密码正确时返回user对象,否则返回None。
        user = auth.authenticate(username=username,password=password)
        if user is not None: #判断user对象是否正确
            auth.login(request,user)  #调用login()函数接收HttpRequest对象和一个user对象
            request.session['user']=username #将session信息记录到浏览器
            response = HttpResponseRedirect('/event_manage/')  #转发到/event_manage/
            return response
        else:
            return render(request,"index.html",{'error':'用户名或密码错误!'})

def event_manage(request):
    #username = request.COOKIES.get('user','') #读取浏览器cookie
    username = request.session.get('user','')
    return render(request,"event_manage.html",{"user":username}) #将username传递到event_manage.html

##代码安全优化
浏览器访问http://127.0.0.1:8000/event_manage/ 发现直接是登录成功,我们要让用户只能通过登录来访问。
修改视图views.py

from django.shortcuts import render    #模板渲染
from django.shortcuts import HttpResponse,HttpResponseRedirect #http返回和http跳转
from django.contrib import auth  #认证
from django.contrib.auth.decorators import login_required  #强制登录

# Create your views here.
def index(request):
    #return HttpResponse("Hello Django!")
    return render(request,"index.html")

def login_action(request):
    if request.method =='POST':
        username = request.POST.get('username','')
        password = request.POST.get('password','')
        #使用authenticate()函数认证给出的用户名和密码。用户名密码正确时返回user对象,否则返回None。
        user = auth.authenticate(username=username,password=password)
        if user is not None: #判断user对象是否正确
            auth.login(request,user)  #调用login()函数接收HttpRequest对象和一个user对象
            request.session['user']=username #将session信息记录到浏览器
            response = HttpResponseRedirect('/event_manage/')  #转发到/event_manage/
            return response
        else:
            return render(request,"index.html",{'error':'用户名或密码错误!'})

@login_required  #强制视图event_manage函数必须登录才能访问
def event_manage(request):
    #username = request.COOKIES.get('user','') #读取浏览器cookie
    username = request.session.get('user','')
    return render(request,"event_manage.html",{"user":username}) #将username传递到event_manage.html

换一个浏览器,访问 http://127.0.0.1:8000/event_manage/,出现404。
在这里插入图片描述观察后发现跳转到 http://127.0.0.1:8000/accounts/login/?next=/event_manage/,“/accounts/login/”需要在ulrs.py配置。

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('login_action/',views.login_action),
    path('event_manage/',views.event_manage),
    path('accounts/login/',views.index),
]

再访问http://127.0.0.1:8000/event_manage/,直接跳到认证页面。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值