美文网首页
3.7Django再说View(2)

3.7Django再说View(2)

作者: 昵称又重复 | 来源:发表于2018-04-27 09:37 被阅读75次

    我会记住生命中不期而遇的温暖 记得大雨磅礴 没有带伞的日子

    不要怕目录长,这可以更好更快的找到你想要的知识点!!!

    奉上目录

    1. Request对象
      1.1 HttpRequest对象
      1.1.1 属性
      1.1.2 方法
      1.2 QueryDict 对象
      1.3 GET 属性
      1.4 POST 属性
    2. Response对象
      2.1 HttpResponse 对象
      2.1.1 属性
      2.1.2 方法
      2.1.3 Cookie
      2.1.3.1 汉字 Cookie 编码问题
      2.1.4 子类HttpResponseRedirect
      2.1.5 子类 JsonResponse
      2.1.6 简写函数
      2.1.6.1 render
      2.1.6.2 重定向
    3. 状态保持
      3.1 启用session
      3.2 使用session
      3.3用户登录示例
      3.4会话过期时间
      3.5存储session
      3.5使用Redis缓存session

    —————————————————————————

    1. Request对象

    1.1 HttpRequest对象

    服务器接收到 http 协议的请求后,会根据报文创建 HttpRequest 对象
     视图函数的第一个参数是 HttpRequest 对象
     在 django.http 模块中定义了 HttpRequest 对象的 API

    —————————————————————————

    1.1.1 属性

    下面除非特别说明,属性都是只读的
     path:一个字符串,表示请求的页面的完整路径,不包含域名.method:一个字符串,表示请求使用的 HTTP 方法,常用值包括: 'GET'、 'POST'

     encoding:一个字符串,表示提交的数据的编码方式,如果为 None ,则表示使用浏览器的默认设置,一般为 utf-8,这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的
    任何访问将使用新的 encoding 值
     GET:一个类似于字典的对象,包含 get 请求方式的所有参数
     POST:一个类似于字典的对象,包含 post 请求方式的所有参数
     FILES:一个类似于字典的对象,包含所有的上传文件
     COOKIES:一个标准的 Python 字典,包含所有的 cookie,键和值都为字符串
     session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当 Django 启
    用会话的支持时才可用,详细内容请找目录:“状态保持“

    —————————————————————————

    1.1.2 方法

    is_ajax():如果请求是通过 XMLHttpRequest 发起的,则返回 True

    —————————————————————————

    1.2 QueryDict 对象

    定义在 django.http.QueryDict
     request 对象的属性 GET、 POST 都是 QueryDict 类型的对象
     与 python 字典不同, QueryDict 类型的对象用来处理同一个键带有多个值的情况
     方法 get():根据键获取值
    注意:
    只能获取键的一个值
    如果一个键同时拥有多个值,获取最后一个值

    dict.get('键',default)
    

    或简写为
    dict['键']
     方法 getlist():根据键获取值
    将键的值以列表返回,可以获取一个键的多个值

    dict.getlist('键',default)
    

    —————————————————————————

    1.3 GET 属性

     QueryDict 类型的对象
     包含 get 请求方式的所有参数
     与 url 请求地址中的参数对应,位于?后面
     参数的格式是键值对,如 key1=value1
     多个参数之间,使用&连接,如 key1=value1&key2=value2
     键是开发人员定下来的,值是可变的
     示例如下
     创建视图 getTest1 用于定义链接, getTest2 用于接收一键一值, getTest3 用于接收一键多值:

    def getTest1(request):
        return render(request,'booktest/getTest1.html')
    def getTest2(request):
        return render(request,'booktest/getTest2.html')
    def getTest3(request):
        return render(request,'booktest/getTest3.html')
    

    项目 url 配置

    urlpatterns = [
        path('admin/', admin.site.urls),
        url(r'^ booktest/', include('booktest.urls',namespace='booktest')),
    ]
    

    应用 url 配置

    url(r'^getTest1/$', views.getTest1),
    url(r'^getTest2/$', views.getTest2),
    url(r'^getTest3/$', views.getTest3),
    

    创建 getTest1.html,定义链接

    <html>
    <head>
    <title>Title</title>
    </head>
    <body>
    链接 1:一个键传递一个值
    <a href=" /booktest/getTest2/?a=1&b=2">gettest2</a><br>
    链接 2:一个键传递多个值
    <a href=" /booktest/getTest3/?a=1&a=2&b=3">gettest3</a>
    </body>
    </html>
    

    完善视图 getTest2 的代码

    def getTest2(request):
    a=request.GET['a']
    b=request.GET['b']
    context={'a':a,'b':b}
    return render(request,'booktest/getTest2.html',context)
    

    创建 getTest2.html,显示接收结果

    <html>
    <head>
    <title>Title</title>
    </head>
    <body>
    a:{{ a }}<br>
    b:{{ b }}
    </body>
    </html>
    

    完善视图 getTest3 的代码

    def getTest3(request):
    a=request.GET.getlist('a')
    b=request.GET['b']
    context={'a':a,'b':b}
    return render(request,'booktest/getTest3.html',context)
    

    创建 getTest3.html,显示接收结果

    <html>
    <head>
    <title>Title</title>
    </head>
    <body>
    a:{% for item in a %}
    {{ item }}
    {% endfor %}
    <br>
    b:{{ b }}
    </body>
    </html>
    

    —————————————————————————

    1.4 POST 属性

    POST 属性
     QueryDict 类型的对象
     包含 post 请求方式的所有参数
     与 form 表单中的控件对应
     问:表单中哪些控件会被提交?
     答:控件要有 name 属性,则 name 属性的值为键, value 属性的值为键,构成键值对提交
     对于 checkbox 控件, name 属性一样为一组,当控件被选中后会被提交,存在一键多值
    的情况
     键是开发人员定下来的,值是可变的
     示例如下
     定义视图 postTest1

    def postTest1(request):
    return render(request,'booktest/postTest1.html')
    

    配置 url

    url(r'^postTest1$',views.postTest1)
    

    创建模板 postTest1.html

    <html>
    <head>
    <title>Title</title>
    </head>
    <body>
    <form method="post" action="/booktest/postTest2/">
        <br />{% csrf_token %}<br />
        姓名: <input type="text" name="uname"/><br>
        密码: <input type="password" name="upwd"/><br>
        性别: <input type="radio" name="ugender" value="1"/>男
        <input type="radio" name="ugender" value="0"/>女<br>
        爱好: <input type="checkbox" name="uhobby" value="胸口碎大石"/>胸口碎大石
        <input type="checkbox" name="uhobby" value="跳楼"/>跳楼
        <input type="checkbox" name="uhobby" value="喝酒"/>喝酒
        <input type="checkbox" name="uhobby" value="爬山"/>爬山<br>
        <input type="submit" value="提交"/>
    </form>
    </body>
    </html>
    

    创建视图 postTest2 接收请求的数据

    def postTest2(request):
        uname=request.POST['uname']
        upwd=request.POST['upwd']
        ugender=request.POST['ugender']
        uhobby=request.POST.getlist('uhobby')
        context={'uname':uname,'upwd':upwd,'ugender':ugender,'uhobby':uhobby}
    return render(request,'booktest/postTest2.html',context)
    

    配置 url

    url(r'^postTest2$',views.postTest2)
    

    创建模板 postTest2.html

    <html>
    <head>
    <title>Title</title>
    </head>
    <body>
        {{ uname }}<br>
        {{ upwd }}<br>
        {{ ugender }}<br>
        {{ uhobby }}
    </body>
    </html>
    

    注意:表单页面添加<br />{% csrf_token %}<br />
     或者给 postTest2 方法添加修饰器@csrf_exempt

    —————————————————————————

    2. Response对象

    2.1 HttpResponse 对象

    在 django.http 模块中定义了 HttpResponse 对象的 API
     HttpRequest 对象由 Django 自动创建, HttpResponse 对象由程序员创建

    不调用模板,直接返回数据

    #coding=utf-8
    from django.http import HttpResponse
    def index(request):
        return HttpResponse('你好')
    

    调用模板

    from django.http import HttpResponse
    from django.template import RequestContext, loader
    def index(request):
        # 获取图书表中所有的记录
        booklist = BookInfo.objects.all()
        # 加载 index.html 模版
        template = loader.get_template('index.html')
        # 字典,用于插入模版中的数据
        context = {'booklist': booklist}
        # 返回模版渲染的结果
        return HttpResponse(template.render(context))
    

    —————————————————————————

    2.1.1 属性

    content:表示返回的内容,字符串类型
     charset:表示 response 采用的编码字符集,字符串类型
     status_code: HTTP 响应状态码
     content-type:指定输出的 MIME 类型

    —————————————————————————

    2.1.2 方法

    init :使用页内容实例化 HttpResponse 对象
     write(content):以文件的方式写
     flush():以文件的方式输出缓存区

    —————————————————————————

    2.1.3 Cookie

    基于 Internet 的各种服务系统应运而生,建立商业站点或者功能比较完善的个人站点,常常需要记录访问者的一些信息;目前公认的是,通过 Cookie 和 Session 技术来实现记录
    访问者的一些基本信息。接下来记录一下 Cookie 的使用:
     response. delete_cookie(key):删除指定的 key 的 Cookie,如果 key 不存在则什么也不发生
     request.COOKIES.get("name")
     response.set_cookie(key, value='', max_age=None, expires=None):设置 Cookie
    key、 value 都是字符串类型
    max_age 是一个整数,表示在指定秒数后过期
    expires 是一个 datetime 或 timedelta 对象,会话将在这个指定的日期/时间过期,注意datetime 和 timedelta 值只有在使用 PickleSerializer 时才可序列化
    max_age 与 expires 二选一
    如果不指定过期时间,则两个星期后过期

    from django.http import HttpResponse
    from datetime import *
    def cookieTest (request):
    response = HttpResponse()
    if 'h1' in request.COOKIES:
    response.write('<h1>' + request.COOKIES['h1'] + '</h1>')
    response.set_cookie('h1', 'hello', 120)
    # response.set_cookie('h1', ''hello'', None, datetime(2016, 10, 31))
    return response
    

    —————————————————————————

    2.1.3.1 汉字 Cookie 编码问题

    当 cookie 值包含中文是, Django 无法执行 response.set_cookie,在服务器控制台报错:
    AttributeError:'NoneType' object has no attribute 'split'
    解决办法:使用 Json

    import json
    def cookieTest2(request):
    response = HttpResponse("OK")
    if 'h1' in request.COOKIES:
    h1 = request.COOKIES['h1']
    response.write('<h1>' + json.loads(h1) + '</h1>')
    response.set_cookie("h1", json.dumps("你好"))
    return response
    

    —————————————————————————

    2.1.4 子类HttpResponseRedirect

    重定向,服务器端跳转
     构造函数的第一个参数用来指定重定向的地址
    在 views1.py 中

    from django.http import HttpResponse,HttpResponseRedirect
    def redirectTest(request):
    #return HttpResponseRedirect(reverse('booktest:getTest1')) #使用反向解析
    return HttpResponseRedirect('http://www.baidu.com')
    

    在应用的 urls.py 中增加一个 url 对象

    url(r'^redirectTest/$', views1.redirectTest, name='getTest1')
    

    —————————————————————————

    2.1.5 子类 JsonResponse

    返回 json 数据,一般用于异步请求
     帮助用户创建 JSON 编码的响应
     参数 data 是字典对象
     JsonResponse 的默认 Content-Type 为 application/json

    from django.http import JsonResponse
    def index2(requeset):
    return JsonResponse({'list': 'abc'})
    

    —————————————————————————

    2.1.6 简写函数

    2.1.6.1 render

     render(request, template_name[, context])
     结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象
     request:该 request 用于生成 response
     template_name:要使用的模板的完整名称
     context:添加到模板上下文的一个字典,视图将在渲染模板之前调用它

    from django.shortcuts import render
    def getTest2(request):
    a = request.GET['a']
    b = request.GET['b']
    context = {'a': a, 'b': b}
    return render(request, 'booktest/getTest2.html', context)
    

    —————————————————————————

    2.1.6.2 重定向

    redirect(to)
     为传递进来的参数返回 HttpResponseRedirect
     推荐使用反向解析

    from django.shortcuts import redirect
    from django.urls import reverse
    def getTest (request):
    return redirect(reverse('booktest:index1'))
    

    应用的 urls.py 中增加一个 url 对象

    url(r'^getTest/$', views.getTest),
    

    得到对象或返回 404
     get_object_or_404(klass, args, *kwargs)
     通过模型管理器或查询集调用 get()方法,如果没找到对象,不引发模型的 DoesNotExist异常,而是引发 Http404 异常
     klass:获取对象的模型类、 Manager 对象或 QuerySet 对象
     **kwargs:查询的参数,格式应该可以被 get()和 filter()接受
     如果找到多个对象将引发 MultipleObjectsReturned 异常

    from django.shortcuts import *
    def detail(request, id):
    try:
    book = get_object_or_404(BookInfo, pk=id)
    except BookInfo.MultipleObjectsReturned:
    book = None
    return render(request, 'booktest/detail.html', {'book': book})
    

    将 settings.py 中的 DEBUG 改为 False
    将请求地址输入 2 和 100 查看效果
    得到列表或返回 404
     get_list_or_404(klass, args, *kwargs)
     klass:获取列表的一个 Model、 Manager 或 QuerySet 实例
     **kwargs:查寻的参数,格式应该可以被 get()和 filter()接受

    from django.shortcuts import *
    def index(request):
    # list = get_list_or_404(BookInfo, pk__lt=1)
    list = get_list_or_404(BookInfo, pk__lt=6)
    return render(request, 'booktest/index.html', {'list': list})
    

    将 settings.py 中的 DEBUG 改为 False

    —————————————————————————

    3.状态保持

    http 协议是无状态的:每次请求都是一次新的请求,不会记得之前通信的状态
     客户端与服务器端的一次通信,就是一次会话
     实现状态保持的方式:在客户端或服务器端存储与会话有关的数据
     存储方式包括 cookie、 session,会话一般指 session 对象
     使用 cookie,所有数据存储在客户端,注意不要存储敏感信息
    推荐使用 sesison 方式,所有数据存储在服务器端,在客户端 cookie 中存储 session_id
     状态保持的目的是在一段时间内跟踪请求者的状态,可以实现跨页面访问当前请求者的数据
     注意:不同的请求者之间不会共享这个数据,与请求者一一对应

    —————————————————————————

    3.1 启用session

    使用 django-admin startproject 创建的项目默认启用
     在 settings.py 文件中
    项 INSTALLED_APPS 列表中添加:

    'django.contrib.sessions',
    

    项 MIDDLEWARE_CLASSES 列表中添加:

    'django.contrib.sessions.middleware.SessionMiddleware',
    

     禁用会话: 默认是开启的, 删除上面指定的两个值,禁用会话将节省一些性能消耗

    —————————————————————————

    3.2 使用session

    启用会话后,每个 HttpRequest 对象将具有一个 session 属性,它是一个类字典对象
     get(key, default=None):根据键获取会话的值
     clear():清除所有会话
     flush():删除当前的会话数据并删除会话的 Cookie
     del request.session['member_id']:删除会话

    —————————————————————————

    3.3用户登录示例(这是一个较为完整的登录项目)

    新建应用 usertest
     在 setting.py 中添加应用
     在 views.py 文件中创建视图

    from django.shortcuts import render, redirect
    from django.urls import reverse
    def index(request):
    uname = request.session.get('uname')
    return render(request, 'usertest/index.html', {'uname': uname})
    def login(request):
    return render(request, 'usertest/login.html')
    @csrf_exempt
    def login_handle(request):
    request.session['uname'] = request.POST['uname']
    return redirect(reverse('usertest:index'))
    def logout(request):
    # request.session['uname'] = None
    # del request.session['uname']
    # request.session.clear()
    request.session.flush()
    return redirect(reverse('usertest:index'))
    

    配置 url
    主 url:

    from django.conf.urls import include, url
    urlpatterns = [
    url(r'^user', include('usertest.urls',namespace='usertest')),
    ]
    

    应用 url:

    from django.conf.urls import url
    from . import views
    urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'login/$', views.login, name='login'),
    url(r'loginhandle/$', views.loginhandle, name='loginhandle'),
    url(r'logout/$', views.logout, name='logout')
    ]
    

     创建模板 index.html

    <!DOCTYPE html>
    <html>
    <head>
    <title>首页</title>
    </head>
    <body>
    你好: {{uname}}
    <hr/>
    <a href="{%url 'main:login'%}">登录</a>
    <hr/>
    <a href="{%url 'main:logout'%}">退出</a>
    </body>
    </html>
    

     创建模板 login.html

    <!DOCTYPE html>
    <html>
    <head>
    <title>登录</title>
    </head>
    <body>
    <form method="post" action="/login_handle/">
    <input type="text" name="uname"/>
    <input type="submit" value="登录"/>
    </form>
    </body>
    </html>
    

    —————————————————————————

    3.4会话过期时间

    set_expiry(value):设置会话的超时时间
     如果没有指定,则两个星期后过期
     如果 value 是一个整数,会话将在 values 秒没有活动后过期
     如果 value 是一个 timedelta 对象,会话将在当前时间加上这个指定的日期/时间过期
     如果 value 为 0,那么用户会话的 Cookie 将在用户的浏览器关闭时过期
     如果 value 为 None,那么会话永不过期
     修改视图中 login_handle 函数,查看效果

    def login_handle(request):
    request.session['uname'] = request.POST['uname']
    # request.session.set_expiry(10)
    # request.session.set_expiry(timedelta(days=5))
    # request.session.set_expiry(0)
    # request.session.set_expiry(None)
    return redirect(reverse('usertest:index'))
    

    —————————————————————————

    3.5存储session

    需要在 setting.py 的 INSTALLED_APPS 设置中添加 django.contrib.sessions
     存储会话的方式
     可以使用 settings.py 的 CACHES 中指定 SESSION_ENGINE 项
     基于数据库的会话
     SESSION_ENGINE='django.contrib.sessions.backends.db'
    django 默认的会话存储方式
     运行 manage.py migrate
     基于缓存的会话

    SESSION_ENGINE='django.contrib.sessions.backends.cache'
    

    只存在本地缓存中,如果丢失则不能找回,比数据库的方式读写更快
     缓存和数据库同时使用

    SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
    

    优先从本地缓存中获取,如果没有则从数据库中获

    —————————————————————————

    3.5使用Redis缓存session

    会话还支持文件、纯 cookie、 Memcached、 Redis 等方式存储,下面演示使用 redis存储
     安装包

    pip install django-redis-sessions==0.5.6
    

     修改 settings 中的配置,增加如下项

    SESSION_ENGINE = 'redis_sessions.session'
    SESSION_REDIS_HOST = 'localhost'
    SESSION_REDIS_PORT = 6379
    SESSION_REDIS_DB = 1
    SESSION_REDIS_PASSWORD = '123'
    SESSION_REDIS_PREFIX = 'session'
    

    View 方法

    def set_session(request):
    """"保存 session 数据"""
    request.session['username'] = 'Django'
    request.session['verify_code'] = '123456
    return HttpResponse('保存 session 数据成功')
    def get_session(request):
    """获取 session 数据"""
    username = request.session.get('username')
    verify_code = request.session.get('verify_code')
    text = 'username=%s, verify_code=%s' % (username, verify_code)
    return HttpResponse(text)
    

    url 配置

    url(r'^set_session$', views.set_session), # 保存 session 数据
    url(r'^get_session$', views.get_session), # 获取 session 数据
    

    查看:

    redis:1>keys *
    "session:otomthrfjr32ms4gt75ovyeld3b4o1fj"
    redis:1>
    

    管理 redis 的命令
    启动:sudo redis-server /etc/redis/redis.conf
    停止:sudo redis-server stop
    重启: sudo redis-server restart
    redis-cli:使用客户端连接服务器
    keys *:查看所有的键
    get name:获取指定键的值
    del name:删除指定名称的键

    —————————————————————————

    感谢语

    感谢茫茫人海中,你点进了我的文章,看见我写的文章都是一种缘,点击进来就是分,有缘分的人,学习到知识之后点点关注吧!还有跟多的精彩文章在后面哦!!!

    相关文章

      网友评论

          本文标题:3.7Django再说View(2)

          本文链接:https://www.haomeiwen.com/subject/firmlftx.html