django的request对象的理解

 

django使用Request对象和Response对象在系统间传递'状态'。

以前误区:

1、request对象,只知道当我们在写django视图的时候,里面的函数需要必须带有request参数,这个参数的名字可以随便起,只要函数的有一个参数即可(非默认参数)。

更正:

当用户发送请求的时候,会创建一个包含用户请求的元数据的HttpRequest对象,当HttpRequest对象经过django的时候,HttpRequest对象传递到视图函数的时候,变为视图的函数的第一个参数。

进过视图函数的处理,返回给用户一个HttpRespone对象。

即开篇说的,django使用Request对象和Reponse对象在django系统间传递状态。

renquest对象的属性:

HttpRequest.body:一个字节字符串,表示原始请求正文,处理常规表单的数据,一般用HttpRequest.POST.

HttpRequest.read():我们可以用类文件形式访问HttpRequest对象的数据。

HttpRequest.path:一个字符串,表示请求的页面的完整路径。不包含域名(即主机名和端口)

http://www.jd.com/a/b/c  其中HttpRequest.path为:/a/b/c

HttpRequest.path_info:在某些Web 服务器配置下,主机名后的URL 部分被分成脚本前缀部分和路径信息部分。path_info 属性将始终包含路径信息部分,不论使用的Web 服务器是什么。使用它代替path 可以让代码在测试和开发环境中更容易地切换。例如,如果应用的WSGIScriptAlias 设置为"/minfo",那么当path 是"/minfo/music/bands/the_beatles/" 时path_info 将是"/music/bands/the_beatles/"

HttpRequest.method:一个字符串,表示使用HTTP方法,method必须为大写。

1 if   request.method=="GET":
2      pass
3 elif  request.method=='POST':
4      pass

 

HttpRequest,encoding:

一个字符串,表示数据的编码格式(如果是None的话,则表示使用DEFAULT_CHARSET 设置) 。这个属性是可写的。你可以修改他来访问body里提交的数据。

 HttpRequest.POST:

是QueryDict的对象,而 QueryDict是继承dict,所以HttpRequest.POST是字典对象。所以字典的方法适用于HttpRequest.POST对象。

HttpRequest.GET:

同样也是QueryDict的对象,所以字典的方法适用于HttpRequest.POST对象。

需要注意:

在判断request的对象的方法的时候,不能以按下面的方法进行判断;

1 def function(request):
2      if request.method=='POST':
3            pass
4       else:
5              pass

 不能以if/else来判断request对象的方法,用else来判断GET 方法,因为HTTP方法不仅是POST和GET,还有PUT、DELETE等方法。

1 if request.POST:
2    pass

 不能以request.POST的字典是否为空值来判断一个是否是POST方法,如果有用户请求的数据的是空,进行GET或者POST请求的时候。

正确:

1 if  request.method=='POST':
2      pass
3 elif  request.method='GET':
4       pass

 HtppRequest.cookie:

  一个标准的python字典,包含的cookie的值,键和值都是字符串。

HttpRequest.FILES:
 一个类似于字典对象,包含所有上传的东西,FILES中的每个键都是<input  name='file_upload'  type='file'>中的name属性,

注意:FILES 只有请求的方法为POST 且提交的form表单带有  enctype="multipart/form-data"的情况下才包含数据,否则该对象类似于空的字典对象。

HttpRequest.META:一个标准的python字典,包含所有的HTTP头部信息。具体的头部信息,取决于客户端和服务器。

常见的头部信息 如下:

 1 CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
 2 CONTENT_TYPE —— 请求的正文的MIME 类型。
 3 HTTP_ACCEPT —— 响应可接收的Content-Type。
 4 HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
 5 HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
 6 HTTP_HOST —— 客服端发送的HTTP Host 头部。
 7 HTTP_REFERER —— Referring 页面。
 8 HTTP_USER_AGENT —— 客户端的user-agent 字符串。
 9 QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
10 REMOTE_ADDR —— 客户端的IP 地址。
11 REMOTE_HOST —— 客户端的主机名。
12 REMOTE_USER —— 服务器认证后的用户。
13 REQUEST_METHOD —— 一个字符串,例如"GET""POST"14 SERVER_NAME —— 服务器的主机名。
15 SERVER_PORT —— 服务器的端口(是一个字符串)。

从上面我们中的REMOTE_ADDR: 获取客户端IP,有时候做接口认证的时候,需要获取客户端的IP。

HttpRequest.user

一个AUTH_USER_MODEL类型对象,表示当前登录用户,前提是使用django的认证系统,如果当前没有登录用户,user将设置django.contrib.models.AnymouseUser的一个实例。

判断当前用户是否登录:

1 if request.user.is_authenticated():
2      #login   do   something you like
3 else:
4       #anymous do something

 request.user.is_authenticated()返回是当前用户的对象,None表示当前用户未登录。

HttpRequest.session:

 一个即可以读,也可以写的字典对象,表示当前登录回话。只有当Django启用会话的支持才可以使用。

启用session:

setting.py文件中的MIDDLEWARE_CLASSES或者MIDDLEWARE中注册一下中间件:

django.contrib.sessions.middleware.SessionMiddleware

以及在INSTALLED_APPS中注册:

1 django.contrib.sessions

 

默认我使用命令创建python   manager  startapp  xxxx的时候已经启用session。

不想启用session 可以把如上两项配置去除。

如果我们不使用django自身的认证系统的时候,我们需要自己设置username以及当我们分页的时候,也需要写入session。

request.session['user']=xxx

如果使用django的认证系统的时候,需要调用login()函数,把当前登录的用户信息写入session中。

 1 from django.contrib.auth import authenticate, login
 2 
 3 def my_view(request):
 4     username = request.POST['username']
 5     password = request.POST['password']
 6     user = authenticate(username=username, password=password)
 7     if user is not None:
 8         login(request, user)#对session进行写入
 9         # Redirect to a success page.
10         ...
11     else:
12         # Return an 'invalid login' error message.
13         ...

去除用户session的信息,直接调用 logout()函数即可。

 二、request的方法:

1、get_host():获取客户端请求的IP和端口。根据从HTTP_X_FORWARDED_HOST(如果打开USE_X_FORWARDED_HOST)和HTTP_HOST 头部信息返回请求的原始主机。如果这两个头部没有提供相应的值,则使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有详细描述。

当主机位于多个代理后面的时候,get_host()会失效,有一个解决方法就是使用中间件重写代理头部。如下:

 1 class MultipleProxyMiddleware(object):
 2     FORWARDED_FOR_FIELDS = [
 3         'HTTP_X_FORWARDED_FOR',
 4         'HTTP_X_FORWARDED_HOST',
 5         'HTTP_X_FORWARDED_SERVER',
 6     ]
 7 
 8     def process_request(self, request):
 9         """
10         Rewrites the proxy headers so that only the most
11         recent proxy is used.
12         """
13         for field in self.FORWARDED_FOR_FIELDS:
14             if field in request.META:
15                 if ',' in request.META[field]:
16                     parts = request.META[field].split(',')
17                     request.META[field] = parts[-1].strip()

该中间件的位置:这个中间件应该放置在所有依赖于get_host() 的中间件之前 —— 例如,CommonMiddleware 和CsrfViewMiddleware

至于中间件书写规则,请参考:http://python.usyiyi.cn/django/index.html

 

MIDDLEWARE_CLASSES中,每一个中间件组件用字符串的方式描述:一个完整的Python全路径加上中间件的类名称。

更多例子:;请参考:http://python.usyiyi.cn/django/index.html

 

posted @ 2017-03-21 19:21  evil_liu  阅读(731)  评论(0)    收藏  举报