Django: handling HTTP requests_安然_随心的博客-程序员秘密

技术标签: python  

原文地址:
https://docs.djangoproject.com/en/2.0/topics/http/
https://docs.djangoproject.com/en/2.0/ref/request-response/

1. 关于HTTP请求和响应

原文地址:https://docs.djangoproject.com/en/2.0/ref/request-response/

当请求一个页面时,Django会创建出一个HttpRequest对象,该对象包含该请求的元数据。然后Django加载合适的(处理该请求的)view(视图处理函数),并将该对象作为视图函数的第一个参数传给它。视图处理函数会返回一个HttpResponse对象。

1.1 HttpRequest对象

1.1.1 属性

该对象包含的属性包括:
(如下这些数据应该是只读的)

  • HttpRequest.scheme:字符串,表示请求的模式(http或是https)
  • HttpRequest.body:byte string,表示原始的http request body;
  • HttpRequest.path:字符串,表示完整的请求路径,不包括http scheme或域,例如:/music/bands/the_beatles/
  • HttpRequest.path_info:
  • HttpRequest.method:字符串,表示请求的方法,例如“GET”,“POST”
  • HttpRequest.encoding:
  • HttpRequest.content_type:
  • HttpRequest.content_params:
  • HttpRequest.GET:一个类字典的对象,包含类所有的HTTP GET参数。
  • HttpRequest.POST:一个类字典对象,包含类所有的HTTP POST参数,包括form表单数据。如果你想获取原始的、非form表单数据,可以通过HttpRequest.body数据获取。对于一个POST方法,可能HttpRequest.POST为空(由于没有包含任何表单数据),因此,如果你想判定请求的方法,不要使用HttpRequest.POST来检查,而是应该使用request.method == "POST"这种形式判定。
  • HttpRequest.COOKIES:字典,包含所有的key,value(都是字符串)
  • HttpRequest.FILES:一个类字典对象,包含类所有的上传文件。FILES中的key是<input type="file" name="" />.中的name。value为一个UploadedFile对象。详情见:https://docs.djangoproject.com/en/2.0/topics/files/ 。只有当请求的方法为POST且 提交的表单 form 包含enctype="multipart/form-data"属性时,FILES才会包含值,否则为一个空的类字典对象。
  • HttpRequest.META:
  • HttpRequest.resolver_match:

被应用代码设置的属性:(Django不会设置这些属性,但是如果你的应用设置了这些属性,则会使用这些值)

  • HttpRequest.current_app:
  • HttpRequest.urlconf:

被中间层设置的属性:

1.1.2 方法

方法包括:

  • HttpRequest.get_host():
  • HttpRequest.get_port():
  • HttpRequest.get_full_path():
  • HttpRequest.build_absolute_uri:
  • HttpRequest.get_signed_cookie:
  • HttpRequest.is_secure():
  • HttpRequest.is_ajax():
  • HttpRequest.read(size=None)/HttpRequest.readline()/HttpRequest.readlines()
  • HttpRequest.__iter__()

1.2 QueryDict对象

在HttpRequest对象中,GET,POST属性都是django.http.QueryDict类型对象。该对象可以处理一个key 绑定多个值的情况(由于html 中存在select multiple这种多个value的情况)。在request.POST,request.GET中的django.http.QueryDict都是不可变的,如果要获取一个可变的版本,可通过QueryDict.copy()获取。https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict.copy

QueryDict实现了所有的标准的字典的方法(它就是一个dictionary的子类)。但是有些的行为可能会存在一点差异(和标准的字典相比)。例如:

  • QueryDict.__init__(query_string=None, mutable=False, encoding=None) :注意request.POST,request.GET中的对象是不可变的,如果你想构造可变的版本,则可传入:mutable=True。
    使用示例:QueryDict('a=1&a=2&c=3')
  • QueryDict.__getitem__(key) :返回给定key的value,如果该key对应多个value,则返回最后一个。如果不存在key ,则抛出异常。
  • QueryDict.__setitem__(key, value)
  • QueryDict.__contains__(key)
  • QueryDict.get(key, default=None)
  • QueryDict.update(other_dict) :将新的值附加到当前列表中(而不是进行替换)。例如:
>>> q = QueryDict('a=1', mutable=True)
>>> q.update({'a': '2'})
>>> q.getlist('a')
['1', '2']
>>> q['a'] # returns the last
'2'
  • QueryDict.items():
  • QueryDict.values():
  • QueryDict.copy():
  • QueryDict.getlist(key, default=None):
  • QueryDict.setlist(key, list_):
  • QueryDict.appendlist(key, item):
  • 还有其他的,懒得粘了

1.3 HttpResponse 对象

HttpResponse是完全由你构造,填充了。

典型的用法是通过一个string来构造httpresponse,例如:

>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")

另外,httpresponse是一个 file-like对象,你可以通过文件读写方法填充内容。

>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")

另外,也可以通过iterator来填充内容。HttpResponse可以消费iterator,然后就内容保存为一个string。如果你想将你的response 通过streaming的方式传递给client,可以使用 StreamingHttpResponse。

1.3.1 设置响应头部

可想操作字典一样,设置头部,例如:

>>> response = HttpResponse()
>>> response['Age'] = 120
>>> del response['Age']

1.3.2 告知浏览器,响应是一个文件附件

to tell the browser to treat the response as a file attachment,通过content_type参数、Content-Disposition头部。例如:

>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename="foo.xls"'

1.3.3 HttpResponse属性

包括:

  • HttpResponse.content:
  • HttpResponse.charset:
  • HttpResponse.status_code:
  • HttpResponse.reason_phrase:
  • HttpResponse.streaming:
  • HttpResponse.closed:

1.3.4 HttpResponse方法

  • HttpResponse.__init__(content='', content_type=None, status=200, reason=None, charset=None)
  • HttpResponse.__setitem__(header, value)
  • HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
  • HttpResponse.write(content)
  • 其他方法,不粘贴了

1.3.5 HttpResponse的子类

包括:

  • HttpResponseRedirect:
  • HttpResponsePermanentRedirect:
  • HttpResponseNotModified:
  • HttpResponseBadRequest:
  • HttpResponseNotFound:
  • HttpResponseForbidden:
  • 其他,不粘贴了

1.4 JsonResponse 对象

HttpResponse的子类,继承了父类的大多数行为,但是,默认情况下,Content-Type 头部为application/json,内容是json-化的对象。

1.5 StreamingHttpResponse 对象与FileResponse 对象

StreamingHttpResponse是HttpResponse的子类。

2.django 对请求的路由处理

当用户请求一个基于Django的页面时,Django通过如下方式找到处理该请求的方法/类(或是没有找到,抛出异常):

  1. Django先确定将要使用的URLConf模块(通常来说,就是setting.py中指定的ROOT_URLCONF(该值一般指定来要使用的URL映射文件))。但是新来的请求HttpRequest对象自己携带来urlconf属性的话,就会使用该值。
  2. 根据ROOT_URLCONF,加载对应的python模块,在模块中寻找urlpatterns变量,该变量的值是一个django.urls.path() 或/和 django.urls.re_path()变量的列表;
  3. Django按顺序检查urlpatterns变量中的每项值,一旦找到一个匹配的URL,就停止,然后Django导入、调用对应的方法。调用时,传入:HttpRequest实例、URL匹配时匹配到的位置参数、其他调用传入的附加参数;

示例:

from django.urls import path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

对于请求 /articles/2005/03/:匹配第三条, Django会调用views.month_archive(request, year=2005, month=3)
/articles/2003/ :匹配第一条,Django调用views.special_case_2003(request)
/articles/2003 :没有匹配;
/articles/2003/03/building-a-django-site/ :匹配最后一条,调用:views.article_detail(request, year=2003, month=3, slug="building-a-django-site").

在写URL匹配规则时,可以使用路径转化器,默认的转化器包括:

  1. str :匹配任意非空自负串,包括/。
  2. int :匹配0或是其他任意的正数,返回一个int值。
  3. slug :Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. For example, building-your-1st-django-site.
  4. uuid : 匹配格式化的uuid。为了避免多个URL匹配到同一个页面,必须包括短横杠(dash),且字符必须是小写的。例如:075194d3-6885-417e-a8a8-6c931e272f00. Returns a UUID instance.
  5. path :匹配任意非空串,包括/。

自定义路径转化器,见:https://docs.djangoproject.com/en/2.0/topics/http/urls/

3. 请求函数的编写

一个处理请求的函数(view function),就是一个简单的python函数,接受一个web请求,然后返回一个web响应。响应可以是html内容,或是一个重定向,或是404错误,或是xml文档或是一个图片,或是其他任意的东西。函数代码也可以放在任意的地方,只要是在python path下。但是一般建议(约定上)放在views.py中。

示例:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

4. 视图装饰器

Django提供了多个装饰器,用于支持不同的Http特征。

4.1 对于http 请求方法的限制过滤

位于django.views.decorators.http 中的装饰器可以提供基于http方法的限制,限制对view 函数的调用。当条件不满足时,这些装饰器会返回django.http.HttpResponseNotAllowed错误。装饰器包括:

  1. require_http_methods(request_method_list) :接受特定的方法请求。例如:
from django.views.decorators.http import require_http_methods

@require_http_methods(["GET", "POST"])
def my_view(request):
    # I can assume now that only GET or POST requests make it this far
    # ...
    pass
  1. require_GET():
  2. require_POST()
  3. require_safe():只允许get,head方法。

4.2 Conditional view processing

位于django.views.decorators.http中的装饰器可以控制对于特定视图的处理caching行为。例如:

  • condition(etag_func=None, last_modified_func=None):
  • etag(etag_func):
  • last_modified(last_modified_func):

这些装饰器可以用于产生ETag,Last-Modified 头部,详细请求见:https://docs.djangoproject.com/en/2.0/topics/conditional-view-processing/

4.3 GZip 压缩

位于Django.views.decorators.gzip中的装饰器可以控制内容压缩行为。装饰器包括:

  • gzip_page():如果浏览器允许gzip压缩的话,该装饰器会压缩内容。

4.4 Vary headers

django.views.decorators.vary包中的装饰器可以用来控制caching行为(基于特定的头部)。装饰器包括:

  • vary_on_cookie(func):
  • vary_on_headers:Vary头部定义了:在构造cache key时,那个request header 应该考虑。

详细见:https://docs.djangoproject.com/en/2.0/topics/cache/#using-vary-headers

4.5 Caching

位于django.views.decorators.cache中的装饰器控制了服务端、客户端的cache,装饰器包括:

  • cache_control(**kwargs) :该装饰器控制http 响应中的Cache-Control头部。
  • never_cache(view_func) :该装饰器控制http 响应中增加Cache-Control: max-age=0, no-cache, no-store, must-revalidate 头部,表示不进行caching。

5. 上传文件

当Django处理文件上传时,文件数据存放在request.FILES变量中。本章主要描述文件如何存储到磁盘或内存中,并如何自定义行为。

对于上传文件的处理:

5.1 示例一:读取

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm

# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

def handle_uploaded_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

5.2 示例二:保存到model 中

保存到model中,可以使用FileField字段类型。当调用form.save函数时,文件数据将会保存到upload_to参数指定的位置

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
from .models import ModelWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            instance = ModelWithFileField(file_field=request.FILES['file'])
            instance.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

5.3 upload handler

当用户上传一个文件时,Django将文件数据传递给upload handler。 upload handler在setting 中的FILE_UPLOAD_HANDLERS变量指定,其初始配置是:

["django.core.files.uploadhandler.MemoryFileUploadHandler",
 "django.core.files.uploadhandler.TemporaryFileUploadHandler"]

Django对于文件的默认处理是:小文件放到内存中,大文件放到磁盘中。

你可以自定义自己的文件处理器,例如增加用户级配置管理,压缩或是将文件存储到其他地方(而非本地)。详见:https://docs.djangoproject.com/en/2.0/ref/files/uploads/#custom-upload-handlers

5.4 upload handler上传数据存储位置

在你对上传的文件做处理前,Django需要将文件存储在某个地方,方便你后续业务的处理。

默认情况下,当文件小于2.5M时,Django会将文件存储在内存中。

如果文件过大,Django会将文件存放到一个临时文件中(位于系统的临时目录中)。在类unix系统中,零时文件类似于:/tmp/tmpzfp6I6.upload。

https://docs.djangoproject.com/en/2.0/ref/settings/#file-upload-settings

6. Django 快捷函数

django.shortcuts 包中提供了一些便捷功能,来增加MVC各层之间的交互功能。例如:

  1. render(request, template_name, context=None, content_type=None, status=None, using=None) :html 文件渲染,将参数填入模版到中。
  2. redirect(to, permanent=False, *args, **kwargs):重定向;
  3. get_object_or_404():在model manager上调用get 方法,如果模型不存在,则返回http404;
  4. get_list_or_404():通过model manager获取过滤后的结果,如果结果为空,则返回http 404;

7. 通用视图

https://docs.djangoproject.com/en/2.0/topics/http/generic-views/

8. 中间层(middleware)

https://docs.djangoproject.com/en/2.0/topics/http/middleware/

Django 的中间层是一种框架,hook into 用户Django 请求/响应处理过程种。它的特点是轻量级的、低层次的‘插件’系统,会全局改变Django的输入输出。

每个中间层组件都完成某种特定的功能,例如AuthenticationMiddleware中间件通过session,将用户与请求绑定。

本章主要描述中间件如何工作且怎么激活中间件、怎么编写自己的中间件。当然,Django也提供来一些内置的中间见,详见:https://docs.djangoproject.com/en/2.0/ref/middleware/

8.1 编写自己的中间件

中间件工厂是一个可调用对象,接受一个get_response 可调用对象,返回一个中间件。

中间件是一个可调用对象,然后返回一个response(和view一样)

示例:

def simple_middleware(get_response):
    # One-time configuration and initialization.

    def middleware(request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

    return middleware

或是,也可以是一个类实例是可调用的类,例如:

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

Django提供的get_response可调用对象可以是真正的view,或是链上的下一个中间件。当前的中间件不需要get_response具体是那种

上述只是一个简化的实例。对于中间件链上的最后一个中间件的get_response实参不会是真正实际的view,而是一个包装器方法,该方法来源于view middleware处理器。

注意:

  • 中间件工厂方法只接受一个参数,即get_response。因此,在__init__()函数中,不能有其他的参数;
  • 对于每次请求,__call__() 方法都会被调用一次,但是__init__()只有在服务器启动时调用一次。

在启动阶段,动态标记那个中间件为“unused":通过在__init__()函数中,抛出MiddlewareNotUsed异常,则Django会将该中间件从链上剔除。

8.2 激活使用中间件

为了启用某个中间件,在MIDDLEWARE 列表(settings.py)中声明你要使用的中间件列表。

在MIDDLEWARE中,每个中间件都表示为一个字符串(该串为中间件工厂的全路径,或是函数名)。例如:(默认配置)

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

在Django项目中,中间件不是必须的, MIDDLEWARE变量可为空,但是,建议你至少使用CommonMiddleware中间件。

8.2.1 中间件的执行顺序和分层

在调用视图函数之前,Django将依次按顺序调用MIDDLEWARE中定义的中间件。一层层调用中间件(像洋葱模型一样)。如果中间的某个中间件做short-cut短路处理,直接返回类response,而不是调用它的get_response,则后续的中间件是看不到请求的。

8.3 中间件hooks

Django中间件必须至少包含以下方法之一:process_request,process_response,process_view 和 process_exception。 这些是由WSGI处理程序收集的方法,然后按列出的顺序调用。

8.3.1process_view

(1)函数声明:
process_view(request, view_func, view_args, view_kwargs)

(2)参数说明:
request:表示HttpRequst 对象。
view_func: 表示Django将要使用的python函数;
view_args,view_kargs:表示传递给view_func的参数。

(3)返回值
process_view函数在Django调用view之间调用。该函数应该返回None或是HttpResponse对象。

如果返回None,则Django会继续处理该请求,执行其他中间件的process_view函数、view函数。

如果返回HttpResponse对象,则Django就不会往后处理了,直接返回给response。

8.3.2 process_exception

当view函数抛出异常时,就会调用中间件的process_exception函数。

8.3.3 process_template_response

(1)函数声明:process_template_response(request, response)

(2)函数参数:
request:http request对象;
response:TemplateResponse对象。该对象由Django view或是其他middleware返回。

process_template_response是在view函数被调用处理完后被调用。如果response实例有render()方法,则表明该response是一个TemplateResponse 对象,或者说等同于一个TemplateResponse 对象。

(3)返回值
该函数必须返回一个实现了render方法的response对象。它可以通过修改response.template_name 或response.context_data ,修改传入的response对象。或是创建一个全新的TemplateResponse对象或是一个类TemplateResponse对象。

你无需显示的对response进行渲染(通过render方法),当所有的template response 中间件都被调用后,response会自动的渲染一次。

process_template_response方法的执行顺序和中间件定义的顺序相反。

各个钩子函数的调用时机如下图所示:
在这里插入图片描述

在这里插入图片描述

8.4 处理流式响应

和httpresponse不同的是StreamingHttpResponse 没有content属性。因此,中间件不能假设所有的response 都有一个content属性。当需要获取content时,你需要对response进行测试,如下:

if response.streaming:
    response.streaming_content = wrap_streaming_content(response.streaming_content)
else:
    response.content = alter_content(response.content)

9. Sessions

https://docs.djangoproject.com/en/2.0/topics/http/sessions/

Django 完全支持匿名session。默认将session数据存储在服务器端,并将cookies中数据的发送和接收过程抽象处理啊。Cookies包含类一个session ID(而不是数据本身)(除非你想将session数据存放到cookie中,详见https://docs.djangoproject.com/en/2.0/topics/http/sessions/#cookie-session-backend)

9.1 启用/禁用session

session是基于中间件实现的。为了允许session机制,你应该做如下配置:

  • 编辑setting中的MIDDLEWARE值,使得包含如下串:django.contrib.sessions.middleware.SessionMiddleware 。通过Django-admin startproject 配置的项目默认包含了该值。

如果你不想使用session,则可在MIDDLEWARE中移除SessionMiddleware中间件串,并在INSTALLED_APPS变量中,移除django.contrib.sessions。

9.2 配置session引擎

默认情况下,Django将session数据存储在数据库中(对应的model为:django.contrib.sessions.models.Session)。但是这可以配置。

如果你想将session存储到数据库中,你需要在INSTALLED_APPS中配置django.contrib.sessions。在配置好后,运行manage.py migrate来安装存储session数据的单个数据表。

9.2.1 将session存储到cache中

将session存储到cache中可以提高存取性能。

在将session存储到cache前,首先检查是否配置来cache。详细见:https://docs.djangoproject.com/en/2.0/topics/cache/

注意:本地cache存储不是线程安全的,因此可能不适合在生成环境下配置本地cache。但是可以配置到像memcache这种cache中。

如果你在CACHES中定义了多个cache,则Django会使用默认的cache。如果要使用其他的cache,将ESSION_CACHE_ALIAS配置成你要使用的cache。

当你配置后cache后,你可以进行如下配置:

  • 设置SESSION_ENGINEdjango.contrib.sessions.backends.cache,配置简单的cache存储。Session将会直接存储到你的cache中。但是,当cache 存储空间满或是服务器重启后,session数据可能不会进行持久化处理;
  • 为了进行持久化,设置SESSION_ENGINEdjango.contrib.sessions.backends.cached_db。这是,会进行写直达(write through)。每次写cache时,也会写入到数据库中。如果数据不在cache中,则会直接到数据库中读取。如果你要使用改种模式,则还需要继续进行配置,详见:https://docs.djangoproject.com/en/2.0/topics/http/sessions/#using-database-backed-sessions

9.2.2 将session存储到文件中

将session存储到文件中,将设置SESSION_ENGINEdjango.contrib.sessions.backends.file

文件式的存储还需要进行配置 SESSION_FILE_PATH,配置文件路径,详见:https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SESSION_FILE_PATH

9.2.3 将session存储到cookie中

将session存储到cookie中,将设置SESSION_ENGINEdjango.contrib.sessions.backends.signed_cookies

9.3 在view中使用session

当启用了SessionMiddleware 后,每个HttpRequest 对象(view的第一个参数)就会有session属性(类字典的对象),然后你可以在view中,通过request.session的方式读写session的值。

9.3.1 backends.base.SessionBase类

该类是所有session对象的基类。该类具有如下方法、及方法的使用示例:

  • __getitem__(key) :使用方式,例如:fav_color = request.session['fav_color']
  • __setitem__(key, value) :使用方式,例如:request.session['fav_color'] = 'blue'
  • __delitem__(key) :可以使用del request.session['fav_color'],但是当key不存在时,会抛出异常;
  • __contains__(key)'fav_color' in request.session
  • get(key, default=None)fav_color = request.session.get('fav_color', 'red')
  • pop(key, default=__not_given)fav_color = request.session.pop('fav_color', 'blue')
  • keys()
  • items()
  • set_expiry(value)
  • flush():删除情况session数据;
  • get_expiry_date()
  • 其他

9.3.2 session的序列化

默认情况下,Django将session组成成json格式。你可以通过SESSION_SERIALIZER 设置来指定使用特定的序列化格式,详见:https://docs.djangoproject.com/en/2.0/topics/http/sessions/#custom-serializers

9.4 在view外使用session

可以通过SessionStore 在 view外使用session。例如:

>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore()
>>> # stored as seconds since epoch since datetimes are not serializable in JSON.
>>> s['last_login'] = 1376587691
>>> s.create()
>>> s.session_key
'2b1189a188b44ad18c35e113ac6ceead'
>>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['last_login']
1376587691

如果你使用db 作为session后端引擎,则可通过model的方式访问操作session。session 相关的model定义在django/contrib/sessions/models.py中。使用示例:

>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/youyou1543724847/article/details/86425408

智能推荐

在VSCode中配置Python运行环境__Naive_的博客-程序员资料

很多时候只需要写一些小脚本,就十几二十行的样子,打开PyCharm什么的太费劲了,可以考虑用VSCode便捷开发。在VSCode中只需要配置好launch,json就可以按F5进行调试了。 打开launch.json:调试 &amp;gt;&amp;gt; 打开配置 修改 pythonpath 词条:&quot;version&quot;: &quot;0.2.0&quot;, &quot;configurations&quot;: [ ...

Hadoop使用lzo压缩并支持分片_xiaoxiongaa0的博客-程序员资料

[[email protected] hive-1.1.0-cdh5.7.0]$ which lzop/bin/lzop[[email protected] data]$ lzop -v page_views_big.dat[[email protected] data]$ ls -lahtotal 1.4Gdrwxrwxr-x 2 hadoop hadoop 4.0K Apr ...

charAt_happy_wealthy的博客-程序员资料

String word = "zhu";word.charAt(1);//取出第一个char,z

在大厂实习三个月后,我竟然迎来了“中年危机“_程序员小濠的博客-程序员资料

中年危机,正在实习生身上蔓延。如今,实习早已经不是大三大四、研二研三求职前的简历演练。越来越多刚步入高校没多久的学生就开始找实习,为“光明的未来”焦虑不已。他们一边兢兢业业做着实习工作,一边在网站上心惊胆战地搜索:“职场上 35 岁以上的人去哪了?”以往人们在 30 岁才到来的中年危机,这种焦虑已经提前发生在 25 岁甚至刚毕业、还没毕业的年轻人身上。整个社会不停地转折、变化、动荡着,如同一架高速运转的机器。处在学校和职场的夹缝中的大厂实习生,如同这架机器的神经末梢,还没成为主要动力,就

区块链水龙头以及常用浏览器地址_xuxizhou1994的博客-程序员资料

1. 比特币BTC水龙头:https://coinfaucet.eu/en/btc-testnet/正式网浏览器地址:https://btc.com/https://explorer.bitcoin.com/btchttps://chain.so/btchttps://live.blockcypher.com/btc/https://www.blockchain.c...

Spring Security实战实用_涛濤的博客-程序员资料

Spring Security安全框架实战单点登陆

随便推点

javaw java 区别,java和javaw之间的区别_喝前尧一尧的博客-程序员资料

I searched to know the difference between java.exe and javaw.exe. I read throughDifference between Java.exe and Javaw.exe.There it is stated that java.exe is for console and javaw.exe is for window ap...

知识点-SpringAOP_盐仓的博客-程序员资料

Spring AOP是什么?我们知道Java是一个面向对象(OOP)的语言,但它有一些弊端,比如当我们需要为多个不具有继承关系的对象引入一个公共行为,例如日志、权限验证、事务等功能时,只能在在每个对象里引用公共行为。这种方式不利于长期维护,且会造成大量重复代码,AOP就可以来弥补OOP的不足,代理模式比如A对象要做一件事情,在没有代理前,自己来做;在对 A 代理后,由 A 的代理类 B 来做。代理其实是在原实例前后加了一层处理,这也是 AOP 的初级轮廓。静态代理原理及实践...

经典Android开发教程!面试字节跳动两轮后被完虐,附面试题答案_程序员Sunbu的博客-程序员资料

前言说起IT行业,大多数人脑海里反应出的第一个标签一定是“高薪”,而说起程序员,大家更多想到的可能是:秃顶、木讷、格子衫;加班多、能赚钱、不花钱;没对象……这难道就是传说中的“国际驰名双标”?程序员难道就不是IT 行业的?上面的都还不是最让人担心的,关键是,网上还有很多人说“程序员在互联网行业里面是吃青春饭的,干到35岁就会被行业淘汰掉”。这下子戳到了大家心里的痛点。为何现在Android应用开发这么难找到工作?随着资本的冷却,整个互联网市场也逐渐的冷静下来.Android应用开发从一开.

《SQL Server 2005实现与维护》之 配置SQL Server 2005_weixin_30664615的博客-程序员资料

一 .配置日志文件和数据文件1. 数据文件分为两种:主数据文件(.mdf):包含数据库目录的启动信息,并且指向其他数据库文件。次数据文件(.ndf):可选的并且是用户定义的,它包含对象和用户数据。通常这样使用他们:将数据库目录存放在主要文件上,将所有的数据和对象存储在次要文件上。2. 数据文件可以分组,称为文件组。通常支持两种文件组:主要文...

计算机专业社会实践报告1500字,计算机专业社会实践报告范文3000字_weixin_39807541的博客-程序员资料

3.每一份影像拷贝(TitleCopy)都有各自的编号Id,同一个影像的若干拷贝编号不同,但是不同的影像拷贝的编号可能会重复。必须记录下是否已经出租,以便于店员随时能够查询拷贝资料的当前状态(status)。4.系统中允许会员预定某项影像资料,但必须提前预约租赁时间(res_date)。5.每一项出租事项需要记录下来(租借日期book_date,实际归还日期act_ret_date,过期时间(ex...

SDDCN架构下的DC内部负载均衡策略-ECMP_cheer1994的博客-程序员资料

云计算中数据中心内部负载均衡策略ECMP背景数据中心的内部网络拓扑通常采用的是Leaf-Spine结构(也称CLOT结构)。这种结构区别于传统的3-Tier结构,任意主机之间两跳可达。主机之间常常存在多条路径。数据中心为了满足吞吐量敏感型流量的需求会提供大量带宽资源。利用SDN控制器对全局网络拓扑感知、路径组员、带宽资源丰富的特性,可以更好的实现负载均衡,将数据流分不到不同路径上进行数据传输,...

推荐文章

热门文章

相关标签