django的view(视图)
一个视图函数,简称视图,是一个简单python函数,他接受web请求并且返回一个响应
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面
一 FBV (function based view) 基于函数视图
例子 :
# FBV版添加班级 def add_class(request): if request.method == "POST": class_name = request.POST.get("class_name") models.Classes.objects.create(name=class_name) return redirect("/class_list/") return render(request, "add_class.html")
二 CBV (class based view) 基于类的视图
例子 :
# CBV版添加班级 from django.views import View # 先引入这个包 class AddClass(View): # 格式 写一个类 下面定义方法(请求方式) 这样写的好处是 不用判断是get换是post方式 def get(self, request): return render(request, "add_class.html") def post(self, request): class_name = request.POST.get("class_name") models.Classes.objects.create(name=class_name) return redirect("/class_list/")
注意:
使用CBV时 urls.py中也要做对应的修改
# urls.py中 url(r'^add_class/$', views.AddClass.as_view()) 这个会自己区分get 和post请求
三 给视图加装饰器
FBV的:(他本身就是一个函数,所以和正常函数,没什么区别,正常在函数上面加就行)
def wrapper(func): def inner(*args, **kwargs): start_time = time.time() ret = func(*args, **kwargs) end_time = time.time() print("used:", end_time-start_time) return ret return inner # FBV版添加班级 @wrapper def add_class(request): if request.method == "POST": class_name = request.POST.get("class_name") models.Classes.objects.create(name=class_name) return redirect("/class_list/") return render(request, "add_class.html")
CBV的:(类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法,我们需要将其转换成方法
方法装饰器)
django给我们提供了 methed_decorator 用于将类中的函数转换成方法装饰器(先导入包
from django.utils.decorators import method_decorator)
加装饰器的三种方法:
1,给某一个方法单独加装饰器: @method_decorator(装饰器函数)
2 给所有请求加 装饰器: 他源码里有个 self.dispatch(request, *args, **kwargs) 函数 self (自己的类) dispatch(这个方法里面有判断 他是get还是post 并通过映射的方式 返回结果) 所以:对了 还有一点 如果你自己的类中有这个方法 他就会优先找自己的(截胡)那你就可以把这个函数写在自己的类中,并在其上面,这样所有的方法都可以有了
3 加在类上: 有个小问题就是你得指定是给哪一类请求 加装饰器:
@method_decorator(装饰器函数,get) # 第三种方式
@method_decorator(装饰器函数,post) # 第三种方式
class Login(View):
@method_decorator(装饰器函数) #第二种方法
def dispatch(self, request, *args, **kwargs):
print('before')
obj = super(Login,self).dispatch(request, *args, **kwargs)
print('after')
return obj
@method_decorator(装饰器函数) # 第一种方法
def get(self,request):
return render(request,'login.html')
def post(self,request):
print(request.POST.get('user'))
return HttpResponse('Login.post')
四 CBV视图加装饰器 如果不使用 提供的模板能用吗 ,区别在哪?
func : <function AddPublisher.get at 0x00000000042CF158> args: (<app01.views.AddPublisher object at 0x000000000440E898>, <WSGIRequest: GET '/add_publisher/'>) func : <function method_decorator.<locals>.dec.<locals>.wrapper.<locals>.bound_func at args: 0x00000000045C71E0> (<WSGIRequest: GET '/add_publisher/'>,)
五 请求相关的常用值
path_info 返回用户访问url,不包括域名
method 请求中使用的HTTP方法的字符串表示,全大写表示。
GET 包含所有HTTP GET参数的类字典对象
POST 包含所有HTTP POST参数的类字典对象
body 请求体,byte类型 request.POST的数据就是从body里面提取到的
六 属性(request相关属性)
属性: django将请求报文中的请求行、头部信息、内容主体封装成 HttpRequest 类中的属性。 除了特殊说明的之外,其他均为只读的。 0.HttpRequest.scheme 表示请求方案的字符串(通常为http或https) 1.HttpRequest.body 一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。 但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。 另外,我们还可以用 python 的类文件方法去操作它,详情参考 HttpRequest.read() 。 2.HttpRequest.path 一个字符串,表示请求的路径组件(不含域名)。 例如:"/music/bands/the_beatles/" 3.HttpRequest.method 一个字符串,表示请求使用的HTTP 方法。必须使用大写。 例如:"GET"、"POST" 4.HttpRequest.encoding 一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。 这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。 接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。 如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。 5.HttpRequest.GET 一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。 6.HttpRequest.POST 一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。 POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。 因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST" 另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。 7.HttpRequest.COOKIES 一个标准的Python 字典,包含所有的cookie。键和值都为字符串。 8.HttpRequest.FILES 一个类似于字典的对象,包含所有的上传文件信息。 FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。 注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会 包含数据。否则,FILES 将为一个空的类似于字典的对象。 9.HttpRequest.META 一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例: CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。 CONTENT_TYPE —— 请求的正文的MIME 类型。 HTTP_ACCEPT —— 响应可接收的Content-Type。 HTTP_ACCEPT_ENCODING —— 响应可接收的编码。 HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。 HTTP_HOST —— 客服端发送的HTTP Host 头部。 HTTP_REFERER —— Referring 页面。 HTTP_USER_AGENT —— 客户端的user-agent 字符串。 QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。 REMOTE_ADDR —— 客户端的IP 地址。 REMOTE_HOST —— 客户端的主机名。 REMOTE_USER —— 服务器认证后的用户。 REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。 SERVER_NAME —— 服务器的主机名。 SERVER_PORT —— 服务器的端口(是一个字符串)。 从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时, 都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。 所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。 10.HttpRequest.user 一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。 如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。 例如: if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users. user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。 ------------------------------------------------------------------------------------- 匿名用户 class models.AnonymousUser django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点: id 永远为None。 username 永远为空字符串。 get_username() 永远返回空字符串。 is_staff 和 is_superuser 永远为False。 is_active 永远为 False。 groups 和 user_permissions 永远为空。 is_anonymous() 返回True 而不是False。 is_authenticated() 返回False 而不是True。 set_password()、check_password()、save() 和delete() 引发 NotImplementedError。 New in Django 1.8: 新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。 11.HttpRequest.session 一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。 完整的细节参见会话的文档。 request属性相关
七 上传文件
def upload(request): if request.method == 'POST': print(request.POST) f1 = request.FILES.get('f1') f1 获得的是一个文件对象 with open(f1.name, 'wb') as f: for i in f1.chunks(): # chunks大文件会自动切断,成一段一段的 f.write(i) return HttpResponse('上传成功') return render(request, 'upload.html')
form表单指定编码方式enctype="multipart/form-data"
八 request对象 和
request属性和方法
print(request.method) # 请求方式 GET POST PUT print(request.GET) # URL携带的参数 { ‘name’: ['alex'] } [] .get('name') print(request.POST) # POST请求提交的数据 { ‘name’: ['alex'] } .getlist() print(request.path_info) # 路径信息 不包含ip和端口 参数 print(request.FILES) print(request.META) print(request.COOKIES) print(request.session) print(request.get_host()) print(request.get_full_path()) # 路径信息 不包含ip和端口 带参数 print(request.is_ajax()) # 判断是否是ajax请求
reponse 属性
HttpResponse('字符串 ') ——》 页面展示 字符串 render(request,'html文件名', { k1:v1 }) ——》 返回一个完整HTML页面 redirect(’要跳转的地址‘) ——》重定向 Location : 地址
JsonResponse: 他跟json序列化不同的是响应头不同 , 他默认只能传字典,相传其他类型加safe=False
from django.http import JsonResponse def json_data(request): data = {'id': 11, 'name': 'alex'} l1 = ['alex', 'peiqi'] return JsonResponse(l1, safe=False) # Content-Type: application/json
序列化可以支持的类型(数字 字典 字符串 none 列表)