Django 之视图篇

    技术2022-07-10  155

    views 视图视图概述其他简单视图HttpResponse详解HttpResponseRedirect Request对象QueryDict对象GET属性POST属性 手动编写视图基于类的视图相关代码

    [欢迎阅读本专栏其他文章] Django 之路由篇 Django 之 Models(Models 模型 & 数据表关系) Django 之模板篇

    views 视图

    视图概述

    视图即视图函数,接收web请求并返回web响应的事务处理函数响应指符合http协议要求的任何内容,包括json,string,html等本章忽略事务处理,重点在如何处理返回结果上

    其他简单视图

    django.http 给我们提供了很多和HttpResponse类似的简单视图,通过查看django.http 代码我们知道此类视图使用方法基本类似,可以通过return语句作为直接反馈返回给浏览器Http404为Exception子类,所以需要raise使用

    HttpResponse详解

    方法 init: 使用网页内容实例化HttpResponse对象write(content): 以文件的方式写flush(): 以文件的方式输出缓存区set_cookie(key, value=’’, max_age=None, expires=None): 设置cookie key, value 都是字符串类型max_age 是一个整数,表示在指定秒数后过期expires 是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期,max_age 与 expires 二选一如果不指定过期时间,则两个星期后过期 delete_cookie(key): 删除指的key的Cookie,如果key不存在则什么也不发生

    HttpResponseRedirect

    重定向,服务器跳转构造函数的第一个参数用来指定重定向的地址

    Request对象

    Request介绍 服务器接收到http协议的请求后,会根据报文创建HttpResponse对象视图函数的第一个参数是HttpResponse对象在django.http 模块中定义了HttpResponse对象的API 属性 下面除非特别说明,属性都是只读的path: 一个字符串,表示请求的页面的完整路径,不包含域名method: 一个字符串,表示请求使用的HTTP方法,常用值包括: ‘GET’, ‘POST’encoding: 一个字符串,表示提交的数据的编码方式 如果为None则表示使用浏览器的默认设置,一般为utf-8这个属性是可写的,可以通过修改它来修改访问表单数据使用 GET: 一个类似于字典的对象,包含get请求方式的所有参数POST: 一个类似于字典的对象,包含post请求方式的所有参数FILES: 一个类似于字典的对象,包含所有的上传文件COOKIES: 一个标准的Python字典,包含所有的cookie,键和值都为字符串session: 一个即可读又可写的类似于字典的对象,表示当前的会话, 只有当Django启用会话的支持时才可用详细内容见"状态保持" 方法 is_ajax(): 如果请求是通过XMLHttpResponse发起的,则返回True

    QueryDict对象

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

    GET属性

    QueryDict类型的对象包含get请求方式的所有参数与url请求地址中的参数对应,位于?后面参数的格式是键值对,即key1 = value1多个参数之间,使用&相连,如key1=value1&key2=value2键是开发人员定下来的,值是可变的案例/views/v12_get def v12_get(request): rst = "" for k,v in request.GET.items(): rst += k + '-->' + v rst += ',' return HttpResponse("Get value of Request is {0}".format(rst))

    POST属性

    QueryDict类型的对象包含post请求方式的所有参数与form表单中的控件对应表单中控件必须有name属性, name为键, value为值 checkbbox存在一键多值的问题 键是开发人员定下来的,值是可变的案例/views/v9_post settint 中设置模板位置设置get页面的urls和函数 def v9_post(request): rst = '' for k, v in request.POST.items(): rst += k + '->' + v rst += ',' return HttpResponse("Get value of POST is {0}".format(rst))

    手动编写视图

    实验目的 利用django快捷函数手动编写视图处理函数编写过程中理解视图运行原理 分析 django把所有请求信息封装入requestdjango通过urls模块把相应请求跟事件处理函数连接起来,并把request作为参数传入在相应的处理函数中,我们需要完成两部分 处理业务把结果封装并返回,我们可以使用HttpResponse,同样也可以自己处理此功能 本案例不介绍业务处理,把目光集中在如何渲染结果并返回 render(request, template_name[, context][, context_instance][, content_type][, status][, current_app][, dirs][, using]) 使用模板和一个给定的上下文环境,返回一个渲染和的HttpResponse对象request: django的传入请求template_name: 模板名称content_instance: 上下文环境案例参看代码 ruochen_views/teacher_app/views/render_test def rander_test(request): # 环境变量 # c = dict() rsp = render(request, "render.html") # rsp = HttpResponse(request, "render.html") return rsp render_to_response 根据给定的上下文字典渲染给定模板,返回渲染后的HttpResponse 系统内建视图

    系统内建视图,可以直接使用

    404

    default.page_not_found(request, template_name=‘404.html’)系统引发Http404时触发默认传递request_path变量给模板,即导致错误的URLDEBUG=True则不会调用404, 取而代之是调试信息404视图会被传递一个RequestContext对象并且可以访问模板上下文处理器提供的变量(MEDIA_URL等)

    500(server error)

    defaults.server_error(request, template_name=‘500.html’)需要DEBUG=False,否则不调用

    403 (HTTP Forbidden) 视图

    defaults.permission_denied(request, template_name=‘403.html’)通过PermissionDenied触发

    400 (bad request) 视图

    defaults.bad_request(request, template_name=‘400.html’)DEBUG=False

    基于类的视图

    简单说一下基于类的视图

    和基于函数的视图的优势和区别: HTTP方法的methode可以有各自的方法,不需要使用条件分支来解决可以使用OOP技术(例如Mixin) 概述 核心是允许使用不同的实例方法来相应不同的HTTP请求方法,而避开条件分支实现as_view函数昨晚类的可调用入库,该方法创建一个实例并调用dispatch方法,按照请求方法对请求进行分发,如果该 方法没有定义,则引发HttpResponseNotAllowed 类属性使用 在类定义时直接覆盖在调用as_view的时候直接昨晚参数使用,例如:urlpatterns = [ url(r'^about/', GreetingView.as_view(greeting="G'day")), ] 对基于类的视图的扩充大致有三种方法: Mixin, 装饰as_view, 装饰dispatch使用Mixin 多继承的一种形式,来自弗雷的行为和属性组合在一起解决多继承问题View的子类只能单继承,多继承会导致不可期问题多继承带来的问题: 结构复杂优先顺序模糊功能冲突 解决方法 规格继承 - java interface实现继承 - python,ruby 在URLconf中装饰from django.contrib.auth.decorators import login_required, permission_required from django.views.generic import TemplateView from .views import VoteView urlpatterns = [ url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))), url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())), ] 装饰类 类的方法和独立方法不同,不能直接运用装饰器,需要用methode_decorator进行装饰from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator from django.views.generic import TemplateView class ProtectedView(TemplateView): template_name = 'secret.html' @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectedView, self).dispatch(*args, **kwargs)

    相关代码

    视图篇用到的相关代码如下

    urls.py from django.conf.urls import include, url from django.contrib import admin from teacher_app import views as v urlpatterns = [ # Examples: # url(r'^$', 'ruochen_views.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^teacher/', v.teacher), url(r'^v2_exp/', v.v2_exception), url(r'^v10_1/', v.v10_1), url(r'^v10_2/', v.v10_2), url(r'^v11_hello/', v.v11, name='v11'), url(r'^v12/', v.v12_get), url(r'^v9_get/', v.v9_get), url(r'^v9_post/', v.v9_post), url(r'render_test/', v.rander_test), url(r'render2_test/', v.rander2_test), url(r'render3_test/', v.rander3_test), url(r'render1_to_res/', v.render4_test), url(r'^get404/', v.get404), ] views.py from django.shortcuts import render, render_to_response from django.http import HttpResponse, Http404, HttpResponseRedirect from django.core.urlresolvers import reverse # Create your views here. def teacher(r): return HttpResponse('这是teacher的一个视图') def v2_exception(r): raise Http404 return HttpResponse('OK') def v10_1(r): return HttpResponseRedirect(reverse('v11')) def v10_2(r): return HttpResponseRedirect(reverse('v11')) def v11(r): return HttpResponse('v11 访问返回') def v12_get(request): rst = "" for k,v in request.GET.items(): rst += k + '-->' + v rst += ',' return HttpResponse("Get value of Request is {0}".format(rst)) def v9_get(request): # 渲染一个模板并返回 return render_to_response('for_post.html') def v9_post(request): rst = '' for k, v in request.POST.items(): rst += k + '->' + v rst += ',' return HttpResponse("Get value of POST is {0}".format(rst)) def rander_test(request): # 环境变量 # c = dict() rsp = render(request, "render.html") # rsp = HttpResponse(request, "render.html") return rsp def rander2_test(request): # 环境变量 c = dict() c['name'] = "ruochen" c['name2'] = "ruochen2" c['name3'] = "ruochen3" rsp = render(request, "render2.html", context=c) return rsp def rander3_test(request): from django.template import loader # 得到模板 t = loader.get_template('render2.html') print(type(t)) r = t.render({"name": "ruochen"}) print(type(r)) return HttpResponse(r) def render4_test(request): # 反馈回m模板render2.html rsp = render_to_response("render2.html", context={"name": "ruochen"}) return rsp def get404(request): from django.views import defaults return defaults.page_not_found(request, template_name="render.html") templates for_post.html <html> <head> <title>Title</title> </head> <body> <form method="post" action="/v9_post/"> 姓名: <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> render.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Render example by ruochen</h1> </body> </html> render2.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>WebPage for rander with {{name}}</h1> </body> </html> settings.py """ Django settings for ruochen_views project. Generated by 'django-admin startproject' using Django 1.8. For more information on this file, see https://docs.djangoproject.com/en/1.8/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.8/ref/settings/ """ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os 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/1.8/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'a^-vz9v!e2ks%m=d*&fu$r)qc42vpgkqny9jl36plg$(3jtp#q' # 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', 'teacher_app', ) MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', ) ROOT_URLCONF = 'ruochen_views.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 = 'ruochen_views.wsgi.application' # Database # https://docs.djangoproject.com/en/1.8/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Internationalization # https://docs.djangoproject.com/en/1.8/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.8/howto/static-files/ STATIC_URL = '/static/'
    Processed: 0.010, SQL: 9