Code前端首页关于Code前端联系我们

Django 如何使用会话?原理、配置及使用

terry 2年前 (2023-09-24) 阅读数 67 #后端开发

1. Django如何使用session

1.1)Session是通过中间件实现的,所以需要先配置MIDDLEWARE

MIDDLEWARE = [
    ... ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    ... ...
]

1.2)默认的session模块是django.contrib.sessions.model.Session,具体参见

# django/conf/global_settings.py
# The module to store session data
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
# Cache to store session data if using the cache session backend.
SESSION_CACHE_ALIAS = 'default'

源码,因此,您需要在 INSTALLED_APPS 中配置

INSTALLED_APPS = [
    ... ...
    'django.contrib.sessions',
    ... ...
]

,然后运行 ​​python manage.py migrate 以使安装高效并使用数据库表来存储会话数据。

当前高版本的Django在项目创建和配置后默认使用数据库存储库。如果不想使用session,可以删除以上两个配置

但如果想使用其他方式保存session,则需要显式配置SESSION_ENGINE等相关配置

2。配置会话模块

2.1。使用数据库存储Session的具体配置请参见上面的介绍。

2.2。使用缓存来存储会话。使用缓存可以提供更好的性能。比如这里使用Redis/Memcached作为缓存

# proj/settings.py
# 先配置CACHE 缓存
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
    },
    'as_session': {
        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

上面配置两个缓存的目的是为了说明Django默认的全局配置SESSION_CACHE_ALIAS默认选择的是‷

‷ 默认当然可以选择其他缓存,比如memcached缓存as_session。此时,您需要显式配置

# proj/settings.py
# Cache to store session data if using the cache session backend.
SESSION_CACHE_ALIAS = 'as_session'
# The module to store session data
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'

2.3。使用文件保存会话

# proj/settings.py
# The module to store session data
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
# 默认是  tempfile.gettempdir()
# 一定要保证对应的程序有权限读写
SESSION_FILE_PATH = '/data/proj/file_session.txt'

2.4。使用cookie来存储session

# proj/settings.py
# The module to store session data
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'

session模块会使用项目配置SECRET_KEY 是Django内置的加密工具(参见https://docs.djangoproject.com/zh-hans/4.1.1.1) .主题/签名/)

2.5。特殊的cached_db存储session其实是除了上述四种方法之外,还有一种组合方法cached_db通过阅读源码,发现源码中的

# django.contrib.sessions.backends.cached_db.py

from django.conf import settings
from django.contrib.sessions.backends.db import SessionStore as DBStore
from django.core.cache import caches

KEY_PREFIX = "django.contrib.sessions.cached_db"


class SessionStore(DBStore):
    """
    Implement cached, database backed sessions.
    """
    cache_key_prefix = KEY_PREFIX

    def __init__(self, session_key=None):
        self._cache = caches[settings.SESSION_CACHE_ALIAS]
        super().__init__(session_key)
    ... ...

DBStore代码实际上是一个基于数据库的会话存储。那么这里cached_db继承自DBStore,然后新增的self._cache是一种基于缓存的Session存储方式。

在视图中使用会话

可以直接在视图中使用request.session,这基本上是HttpResquest对象的会话属性。

为什么可以直接使用?主要是通过SessionMiddleware来体现

# django/contrib/sessions/middleware.py

from django.utils.deprecation import MiddlewareMixin

class SessionMiddleware(MiddlewareMixin):
    # RemovedInDjango40Warning: when the deprecation ends, replace with:
    #   def __init__(self, get_response):
    def __init__(self, get_response=None):
        super().__init__(get_response)
        engine = import_module(settings.SESSION_ENGINE)
        self.SessionStore = engine.SessionStore

    def process_request(self, request):
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
        # 核心代码
        request.session = self.SessionStore(session_key)

,然后所有的会话引擎都继承自SessionBase。这个类提供了一些标准的字典方法

# django/contrib/sessions/backends/base.py

class SessionBase:
    def __getitem__(self, key):
        # val = request.session[key]
        ... ...
    def __setitem__(self, key):
        # request.session[key] = val
        ... ...
    def __delitem__(self, key):
        # del request.session[key]
        ... ...
    def __contains__(self, key):
        # key in request.session
        ... ...
    def get(self, key, default=None):
        # val = request.session.get('key', 'default_val')
        ... ...
    def pop(self, key, default=__not_given):
        # val = request.session.get('key', 'default_val')
        ... ...
    ... ...  

,还有很多像set_expiry()\cycle_key()等方法,如果有兴趣可以自己查看源码

吗?实际使用过程中有几个注意事项

1。强烈建议使用 JSON 序列化,即使是自定义序列化。这就是 Django 的顺序会话默认的使用方式。

SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'

2。 request.session 使用常见的Python字符串作为字典键。不要使用以下划线开头。这是保留给 Django 内部使用的

3。不要覆盖 request.session 只需将其用作常规 Python 字典即可。

使用示例

def login(request):
    user = User.objects.get(username=request.POST['username'])
    if user.check_password(request.POST['password']):
        # 登录成功之后,保存用户ID到session中,用于后续判断
        request.session['user_id'] = user.id
        return HttpResponse("You're logged in.")
    else:
        return HttpResponse("Your username and password didn't match.")

在视图外使用会话

基础是在自己的代码中导入所需的会话存储模块,建议使用import_module方法,

# 直接导入
from django.contrib.sessions.backends.db import SessionStore
s = SessionStore()

# 建议 import_Module方式
>>> from importlib import import_module
>>> from django.conf import settings
>>> SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
>>> s = SessionStore()
>>> s
<django.contrib.sessions.backends.db.SessionStore object at 0x102ac6160>
>>> s['username'] = 'James'
>>> s.session_key
>>> s.create()
>>> s.session_key
'v75esxsbrye4efrl3tppsp6w443jawq5'
>>> s2 = SessionStore(session_key='v75esxsbrye4efrl3tppsp6w443jawq5')
>>> s2['username']
'James'
>>> s2.session_key
'v75esxsbrye4efrl3tppsp6w443jawq5'

扩展介绍-会话持久化

在会话V相关配置中,SESSION_EXPIRE_AT_BROWSER_CLOSE用于控制会话是否在上使用持久会话♷或❙♷ • 当 _EXPIRE_AT_BROWSER_CLOSE=True 时会话 Django当使用 浏览器长度 ♷ 时,表示浏览器关闭,会话自动过期

  • • SESSION_gojanWIRE_SE❙ SESSION_gojanWIRE_SE 永久会话
  • 表示浏览器关闭,会话通过 SESSION_COOKIE_AGE 过期后 当然,除了上面的全局变量来控制会话过期之外,你还可以显式地使用 request.session 中的 set_expiry() 在每个会话级别进行覆盖

    扩展简介 - 清理会话

    1。如果session存储在db或者文件中,那么Django不提供自动删除过期session的功能,需要调整过期session的定期删除。

    建议使用Django提供的内置clearesessions命令

    2。如果使用缓存或cookie,则具有过期后自动删除的功能。无需人工干预。

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门