---
title: "Conas seisiúin a úsáid"
version: 6.1
locale: ga
source: https://docs.djangoproject.com/ga/6.1/topics/http/sessions/
canonical: https://djangodocs.dev/ga/6.1/topics/http/sessions/
---
# Conas seisiúin a úsáid

Soláthraíonn Django tacaíocht iomlán do sheisiúin gan ainm. Ligeann creat an seisiúin duit sonraí treallach a stóráil agus a aisghabháil ar bhonn cuairteora in aghaidh an láithre Stórálann sé sonraí ar thaobh an fhreastalaí agus déanann sé achoimrí ar sheoladh agus a fháil fianáin. \<cookie-session-backend\>Tá aitheantas seisiúin i bhfianáin - ní na sonraí féin (mura bhfuil tú ag úsáid an:ref: backend bhunaithe ar fianáin ).

## Seisiúin chumasaithe

Cuirtear seisiúin i bhfeidhm trí phíosa de:doc: middleware \</ref/middleware\>.

Chun feidhmiúlacht seisiúin a chumasú, déan an méid seo

- Cuir an socrú:setting: MIDDLEWARE in eagar agus déan cinnte go bhfuil ``Django.contrib.sessions.middleware.sessionMiddleware'` ann. Tá `SessionMiddleware`` gníomhachtaithe ag `django-admin startproject` réamhshocraithe `settings.py`.

Mura dteastaíonn uait seisiúin a úsáid, b'fhéidir go bhfaighidh tú an líne `SessionMiddleware` ó:setting: MIDDLEWARE agus django.contrib.sessions' \`\`ó d':setting: \`INSTALLED\_APPS. Sábhálfaidh sé beagán laochairde duit.

## Inneall an seisiúin a chumrú

De réir réamhshocraithe, stórálann Django seisiúin i do bhunachar sonraí (ag baint úsáide as an tsamhail Django.Contrib.Sessions.Models.Session ). Cé go bhfuil sé seo áisiúil, i roinnt socruithe tá sé níos tapúla sonraí seisiúin a stóráil in áiteanna eile, mar sin is féidir Django a chumrú chun sonraí seisiúin a stóráil ar do chóras comhaid nó i do taisce.

### Ag baint úsáide as seisiúin tacaithe

Más mian leat seisiún tacaíochta le bunachar sonraí a úsáid, ní mór duit django.contrib.sessions'\` a chur le do shuíomh: INSTALLED\_APPS.

Nuair a bheidh do shuiteáil cumraithe agat, reáchtáil `manage.py migrate` chun an tábla bunachar sonraí aonair a stóráil sonraí seisiúin a shuiteáil.

### Seisiúin taisceáilte a úsáid

Le haghaidh feidhmíochta níos fearr, b'fhéidir gur mhaith leat cúltaca seisiúin bunaithe ar taisce a úsáid.

Chun sonraí seisiúin a stóráil ag baint úsáide as córas taisce Django, beidh ort a chinntiú go bhfuil do taisce cumraithe agat ar dtús; féach an:doc: cáipéisíocht taisceach le haghaidh sonraí \</topics/cache\>.

> **Warning**
>
> Níor chóir duit seisiúin cach-bhunaithe a úsáid ach má tá cúltaca taisce Memcached nó Redis á úsáid agat. Ní choinníonn an cúltaca taisce cuimhne áitiúil sonraí fada go leor le bheith ina rogha maith, agus beidh sé níos tapúla seisiúin comhad nó bunachar sonraí a úsáid go díreach in ionad gach rud a sheoladh tríd an gcúltaca taisce comhaid nó bunachar sonraí. Ina theannta sin, NÍL cúltaca taisce cuimhne áitiúil sábháilte ilphróisis, dá bhrí sin is dócha nach rogha maith é do thimpeallachtaí táirgeachta.

Má tá iliomad taisce sainithe agat in:setting: CACHES, úsáidfidh Django an taisce réamhshocraithe. Chun taisce eile a úsáid, socraí:setting: SESSION\_CACHE\_ALIAS ar ainm an taisce sin.

Nuair a bheidh do taisce cumraithe, caithfidh tú a roghnú idir taisce tacaíochta bunachar sonraí nó taisce neamh-leanúnach.

Úsáideann cúltaca an bhunachar sonraí taisceáilte (cached\_db\`) taisce scríbhneoireachta - cuirtear scríbhneoireachtaí seisiúin i bhfeidhm ar an mbunachar sonraí agus taisce araon, san ord sin. Má theipeann ar scríobh chuig an taisce, déantar an eisceacht a láimhseáil agus a logáil trí:ref: session logger \<django-contrib-sessions-logger\>, chun a sheachaint ar oibríocht scríbhneoireachta rathúil ar shlí eile.

Úsáideann léitheanna seisiúin an taisce, nó an bunachar sonraí má dhíothraíodh na sonraí ón taisce. Chun an cúltaca seo a úsáid, socraí:setting: SESSION\_ENGINE go `"django.contrib.sessions.backends.cached_db"`, agus lean na treoracha cumraíochta do [úsáid seisiúin tacaíochta bunachar sonraí](#using-database-backed-sessions).

Ní stórálann an cúltaca taisce (`cache`) sonraí seisiúin amháin i do taisce. Tá sé seo níos gasta toisc go seachnaíonn sé marthanacht bunachar sonraí, ach beidh ort machnamh a dhéanamh ar cad a tharlaíonn nuair a dhéantar sonraí taisce a dhíbirt. Is féidir le díothú tarlú má líonann an taisce nó má athosaítear an freastalaí taisce, agus ciallaíonn sé go gcailltear sonraí seisiúin, lena n-áirítear úsáideoirí logáil amach. Chun an cúltaca seo a úsáid, socraí:setting: SESSION\_ENGINE go `"django.contrib.sessions.backends.cache"`.

Is féidir an cúltaca taisce a dhéanamh leanúnach trí taisce leanúnach a úsáid, mar shampla Redis le cumraíocht chuí. Ach mura bhfuil do taisce cumraithe cinnte le haghaidh marthanacht leordhóthanach, roghnaigh cúltaca an bhunachar sonraí taisceáilte. Seachnaíonn sé seo cásanna imeall de bharr stóráil sonraí neamhiontaofa sa táirge

### Ag baint úsáide as seisiúin comhad

Chun seisiúin comhadbhunaithe a úsáid, socraigh an socrú:setting: SESSION\_ENGINE go `"django.contrib.sessions.backends.file"`.

B'fhéidir gur mhaith leat an socrú: setting: SESSION\_FILE\_PATH a shocrú (a réamhshocraíonn aschur ó tempfile.gettempdir () \`, is dóichí `/tmp`) chun rialú a dhéanamh ar an áit a stórálann Django comhaid seisiúin. Bí cinnte a sheiceáil go bhfuil ceadanna ag do fhreastalaí gréasáin chun léamh agus scríobh chuig an áit seo.

### Seisiúin bunaithe ar fhianán a úsáid

Chun seisiúin bunaithe ar fhianáin a úsáid, socraigh an socrú:setting: SESSION\_ENGINE go `"django.contrib.sessions.backends.signed_cookies"`. Stórálfar sonraí na seisiúin ag baint úsáide as uirlisí Django le haghaidh: doc: síniú cripteagrafach' agus an socrú:: \`SECRET\_KEY. \</topics/signing\>

> **Note**
>
> Moltar an socrú:setting: SESSION\_COOKIE\_HTTPONLY a fhágáil ar True\` chun rochtain ar na sonraí stóráilte ó JavaScript a chosc.

> **Warning**
>
> \*\* Sínítear sonraí na seisiúin ach níl siad criptithe
>
> Nuair a bhíonn cúltaca na fianáin á n-úsáid agat is féidir leis an gcliant sonraí na seisiúin a léamh.
>
> Úsáidtear MAC (Cód Fíordheimhnithe Teachtaireachta) chun na sonraí a chosaint ar athruithe a dhéanann an chliant, ionas go ndéanfar sonraí na seisiúin neamhbhailí agus iad ag cur isteach orthu. Tarlaíonn an neamhbhailí céanna mura féidir leis an gcliant atá ag stóráil an fianán (m.sh. brabhsálaí d'úsáideora) an fianán seisiúin go léir a stóráil agus scaoileann \<2965 #section -5.3\>Cé go gcomhbhrúiteann Django na sonraí, is féidir go hiomlán fós an: rfc: teorainn choiteann de 4096 baite' in aghaidh an fhianáin a shárú.
>
> \*\* Gan aon ráthaíocht úire\*\*
>
> Tabhair faoi deara freisin cé gur féidir leis an MAC barántúlacht na sonraí a ráthú (gur ghin do shuíomh iad, agus ní duine eile), agus sláine na sonraí (go bhfuil sé ar fad ann agus ceart), ní féidir leis úire a ráthú ie go bhfuil tú á sheoladh ar ais an rud deireanach a chuir tú chuig an gcliant. Ciallaíonn sé seo, i gcás roinnt úsáidí sonraí seisiúin, d'fhéadfadh cúltaca fianán tú a oscailt chun ionsaithe a athsheinm \`\_. Murab ionann agus cúltaca seisiúin eile a choinníonn taifead taobh an fhreastalaí de gach seisiún agus a chuireann neamhbhailí é nuair a logálann úsáideoir amach, ní chuirtear seisiúin bunaithe ar fhianán neamhbhailí nuair a logálann Mar sin má ghoideann ionsaitheoir fianán úsáideora, is féidir leo an fianán sin a úsáid chun logáil isteach mar an úsáideoir sin fiú má logálann an t-úsáideoir amach. Ní bhraithfear fianáin mar 'seasmhach' ach amháin má tá siad níos sine ná leat:setting: \`SESSION\_COOKIE\_AGE.
>
> **Feidhmíocht**
>
> Faoi dheireadh, is féidir le méid fianán tionchar a imirt ar luas do shuíomh.

## Seisiúin a úsáid i radhairc

Nuair a chuirtear SessionMiddleWare\` i ngníomh, beidh tréith `seisiúna` ag gach rud: ~django.http.httpRequest \- an chéad argóint d'aon fheidhm amharc Django -- tréith `seisiú`, ar réad cosúil le foclóir é.

Is féidir leat é a léamh agus scríobh chuig request.session ag aon phointe i do thuairim. Is féidir leat é a chur in eagar arís agus arís eile.

#### `class backends.base.SessionBase`

Is é seo an bunaicme do gach réad seisiúin. Tá na modhanna caighdeánacha foclóra seo a leanas aige:

#### `__getitem__(key)`

Sampla: fav\_color = iarrat.session \['fav\_color'\] \`\`

#### `__setitem__(key, value)`

Sampla: request.session \['fav\_color'\] = 'blue' \`\`

#### `__delitem__(key)`

Example: `del request.session['fav_color']`. This raises `KeyError`
if the given `key` isn't already in the session.

#### `__contains__(key)`

Example: `'fav_color' in request.session`

#### `__bool__()`

> **New in Django 6.1**

Returns the inverse of [`is_empty()`](#django.contrib.sessions.backends.base.SessionBase.is_empty). This allows checking if a
session has data:

```
if request.session:
    # Session has data or a key
    pass
```

#### `get(key, default=None)`

#### `aget(key, default=None)`

*Leagan asincrón*: aget () \`\`

Example: `fav_color = request.session.get('fav_color', 'red')`

#### `aset(key, value)`

Example: `await request.session.aset('fav_color', 'red')`

#### `update(dict)`

#### `aupdate(dict)`

*Asynchronous version*: `aupdate()`

Example: `request.session.update({'fav_color': 'red'})`

#### `pop(key, default=__not_given)`

#### `apop(key, default=__not_given)`

*Asynchronous version*: `apop()`

Example: `fav_color = request.session.pop('fav_color', 'blue')`

#### `keys()`

#### `akeys()`

*Asynchronous version*: `akeys()`

#### `values()`

#### `avalues()`

*Asynchronous version*: `avalues()`

#### `has_key(key)`

#### `ahas_key(key)`

*Asynchronous version*: `ahas_key()`

#### `items()`

#### `aitems()`

*Asynchronous version*: `aitems()`

#### `setdefault()`

#### `asetdefault()`

*Asynchronous version*: `asetdefault()`

#### `clear()`

It also has these methods:

#### `flush()`

#### `aflush()`

*Asynchronous version*: `aflush()`

Deletes the current session data from the session and deletes the session
cookie. This is used if you want to ensure that the previous session data
can't be accessed again from the user's browser (for example, the
[`django.contrib.auth.logout()`](/ga/6.1/topics/auth/default/#django.contrib.auth.logout) function calls it).

#### `is_empty()`

Returns `True` if the session does not have a key and is empty.

#### `set_test_cookie()`

#### `aset_test_cookie()`

*Asynchronous version*: `aset_test_cookie()`

Sets a test cookie to determine whether the user's browser supports
cookies. Due to the way cookies work, you won't be able to test this
until the user's next page request. See [Setting test cookies](#setting-test-cookies) below for
more information.

#### `test_cookie_worked()`

#### `atest_cookie_worked()`

*Asynchronous version*: `atest_cookie_worked()`

Returns either `True` or `False`, depending on whether the user's
browser accepted the test cookie. Due to the way cookies work, you'll
have to call `set_test_cookie()` or `aset_test_cookie()` on a
previous, separate page request.
See [Setting test cookies](#setting-test-cookies) below for more information.

#### `delete_test_cookie()`

#### `adelete_test_cookie()`

*Asynchronous version*: `adelete_test_cookie()`

Deletes the test cookie. Use this to clean up after yourself.

#### `get_session_cookie_age()`

Returns the value of the setting [`SESSION_COOKIE_AGE`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_AGE). This can
be overridden in a custom session backend.

#### `set_expiry(value)`

#### `aset_expiry(value)`

*Asynchronous version*: `aset_expiry()`

Sets the expiration time for the session. You can pass a number of
different values:

- If `value` is an integer, the session will expire after that
  many seconds of inactivity. For example, calling
  `request.session.set_expiry(300)` would make the session expire
  in 5 minutes.
- If `value` is a `datetime` or `timedelta` object, the session
  will expire at that specific date/time.
- If `value` is `0`, the user's session cookie will expire
  when the user's web browser is closed.
- If `value` is `None`, the session reverts to using the global
  session expiry policy.

Reading a session is not considered activity for expiration
purposes. Session expiration is computed from the last time the
session was *modified*.

#### `get_expiry_age()`

#### `aget_expiry_age()`

*Asynchronous version*: `aget_expiry_age()`

Returns the number of seconds until this session expires. For sessions
with no custom expiration (or those set to expire at browser close), this
will equal [`SESSION_COOKIE_AGE`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_AGE).

This function accepts two optional keyword arguments:

- `modification`: last modification of the session, as a
  [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) object. Defaults to the current time.
- `expiry`: expiry information for the session, as a
  [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) object, an [`int`](https://docs.python.org/3/library/functions.html#int) (in seconds), or
  `None`. Defaults to the value stored in the session by
  [`set_expiry()`](#django.contrib.sessions.backends.base.SessionBase.set_expiry)/[`aset_expiry()`](#django.contrib.sessions.backends.base.SessionBase.aset_expiry), if there is one, or `None`.

> **Note**
>
> This method is used by session backends to determine the session expiry
> age in seconds when saving the session. It is not really intended for
> usage outside of that context.
>
> In particular, while it is **possible** to determine the remaining
> lifetime of a session **just when** you have the correct
> `modification` value **and** the `expiry` is set as a `datetime`
> object, where you do have the `modification` value, it is more
> straight-forward to calculate the expiry by-hand:
>
> ```
> expires_at = modification + timedelta(seconds=settings.SESSION_COOKIE_AGE)
> ```

#### `get_expiry_date()`

#### `aget_expiry_date()`

*Asynchronous version*: `aget_expiry_date()`

Returns the date this session will expire. For sessions with no custom
expiration (or those set to expire at browser close), this will equal the
date [`SESSION_COOKIE_AGE`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_AGE) seconds from now.

This function accepts the same keyword arguments as
[`get_expiry_age()`](#django.contrib.sessions.backends.base.SessionBase.get_expiry_age), and similar notes on usage apply.

#### `get_expire_at_browser_close()`

#### `aget_expire_at_browser_close()`

*Asynchronous version*: `aget_expire_at_browser_close()`

Returns either `True` or `False`, depending on whether the user's
session cookie will expire when the user's web browser is closed.

#### `clear_expired()`

#### `aclear_expired()`

*Asynchronous version*: `aclear_expired()`

Removes expired sessions from the session store. This class method is
called by [`clearsessions`](/ga/6.1/ref/django-admin/#django-admin-clearsessions).

#### `cycle_key()`

#### `acycle_key()`

*Asynchronous version*: `acycle_key()`

Creates a new session key while retaining the current session data.
[`django.contrib.auth.login()`](/ga/6.1/topics/auth/default/#django.contrib.auth.login) calls this method to mitigate against
session fixation.

### Session serialization

By default, Django serializes session data using JSON. You can use the
[`SESSION_SERIALIZER`](/ga/6.1/ref/settings/#std-setting-SESSION_SERIALIZER) setting to customize the session serialization
format. Even with the caveats described in [Write your own serializer](#custom-serializers), we highly
recommend sticking with JSON serialization *especially if you are using the
cookie backend*.

For example, here's an attack scenario if you use [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle) to serialize
session data. If you're using the [signed cookie session backend](#cookie-session-backend) and [`SECRET_KEY`](/ga/6.1/ref/settings/#std-setting-SECRET_KEY) (or any key of
[`SECRET_KEY_FALLBACKS`](/ga/6.1/ref/settings/#std-setting-SECRET_KEY_FALLBACKS)) is known by an attacker (there isn't an
inherent vulnerability in Django that would cause it to leak), the attacker
could insert a string into their session which, when unpickled, executes
arbitrary code on the server. The technique for doing so is simple and easily
available on the internet. Although the cookie session storage signs the
cookie-stored data to prevent tampering, a [`SECRET_KEY`](/ga/6.1/ref/settings/#std-setting-SECRET_KEY) leak
immediately escalates to a remote code execution vulnerability.

#### Bundled serializers

#### `class serializers.JSONSerializer`

A wrapper around the JSON serializer from [`django.core.signing`](/ga/6.1/topics/signing/#module-django.core.signing). Can
only serialize basic data types.

In addition, as JSON supports only string keys, note that using non-string
keys in `request.session` won't work as expected:

```pycon
>>> # initial assignment
>>> request.session[0] = "bar"
>>> # subsequent requests following serialization & deserialization
>>> # of session data
>>> request.session[0]  # KeyError
>>> request.session["0"]
'bar'
```

Similarly, data that can't be encoded in JSON, such as non-UTF8 bytes like
`'\xd9'` (which raises [`UnicodeDecodeError`](https://docs.python.org/3/library/exceptions.html#UnicodeDecodeError)), can't be stored.

See the [Write your own serializer](#custom-serializers) section for more details on limitations
of JSON serialization.

#### Write your own serializer

Note that the [`JSONSerializer`](#django.contrib.sessions.serializers.JSONSerializer)
cannot handle arbitrary Python data types. As is often the case, there is a
trade-off between convenience and security. If you wish to store more advanced
data types including `datetime` and `Decimal` in JSON backed sessions, you
will need to write a custom serializer (or convert such values to a JSON
serializable object before storing them in `request.session`). While
serializing these values is often straightforward
([`DjangoJSONEncoder`](/ga/6.1/topics/serialization/#django.core.serializers.json.DjangoJSONEncoder) may be helpful),
writing a decoder that can reliably get back the same thing that you put in is
more fragile. For example, you run the risk of returning a `datetime` that
was actually a string that just happened to be in the same format chosen for
`datetime`s.

Your serializer class must implement two methods,
`dumps(self, obj)` and `loads(self, data)`, to serialize and deserialize
the dictionary of session data, respectively.

### Session object guidelines

- Use normal Python strings as dictionary keys on `request.session`. This
  is more of a convention than a hard-and-fast rule.
- Session dictionary keys that begin with an underscore are reserved for
  internal use by Django.
- Don't override `request.session` with a new object, and don't access or
  set its attributes. Use it like a Python dictionary.

### Samplaí

This simplistic view sets a `has_commented` variable to `True` after a user
posts a comment. It doesn't let a user post a comment more than once:

```
def post_comment(request, new_comment):
    if request.session.get("has_commented", False):
        return HttpResponse("You've already commented.")
    c = comments.Comment(comment=new_comment)
    c.save()
    request.session["has_commented"] = True
    return HttpResponse("Thanks for your comment!")
```

This simplistic view logs in a "member" of the site:

```
def login(request):
    m = Member.objects.get(username=request.POST["username"])
    if m.check_password(request.POST["password"]):
        request.session["member_id"] = m.id
        return HttpResponse("You're logged in.")
    else:
        return HttpResponse("Your username and password didn't match.")
```

...And this one logs a member out, according to `login()` above:

```
def logout(request):
    try:
        del request.session["member_id"]
    except KeyError:
        pass
    return HttpResponse("You're logged out.")
```

The standard [`django.contrib.auth.logout()`](/ga/6.1/topics/auth/default/#django.contrib.auth.logout) function actually does a bit
more than this to prevent inadvertent data leakage. It calls the
[`flush()`](#django.contrib.sessions.backends.base.SessionBase.flush) method of `request.session`.
We are using this example as a demonstration of how to work with session
objects, not as a full `logout()` implementation.

## Setting test cookies

As a convenience, Django provides a way to test whether the user's browser
accepts cookies. Call the [`set_test_cookie()`](#django.contrib.sessions.backends.base.SessionBase.set_test_cookie)
method of `request.session` in a view, and call
[`test_cookie_worked()`](#django.contrib.sessions.backends.base.SessionBase.test_cookie_worked) in a subsequent view --
not in the same view call.

This awkward split between `set_test_cookie()` and `test_cookie_worked()`
is necessary due to the way cookies work. When you set a cookie, you can't
actually tell whether a browser accepted it until the browser's next request.

It's good practice to use
[`delete_test_cookie()`](#django.contrib.sessions.backends.base.SessionBase.delete_test_cookie) to clean up after
yourself. Do this after you've verified that the test cookie worked.

Here's a typical usage example:

```
from django.http import HttpResponse
from django.shortcuts import render

def login(request):
    if request.method == "POST":
        if request.session.test_cookie_worked():
            request.session.delete_test_cookie()
            return HttpResponse("You're logged in.")
        else:
            return HttpResponse("Please enable cookies and try again.")
    request.session.set_test_cookie()
    return render(request, "foo/login_form.html")
```

## Using sessions out of views

> **Note**
>
> The examples in this section import the `SessionStore` object directly
> from the `django.contrib.sessions.backends.db` backend. In your own code,
> you should consider importing `SessionStore` from the session engine
> designated by [`SESSION_ENGINE`](/ga/6.1/ref/settings/#std-setting-SESSION_ENGINE), as below:
>
> ```pycon
> >>> from importlib import import_module
> >>> from django.conf import settings
> >>> SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
> ```

An API is available to manipulate session data outside of a view:

```pycon
>>> 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
```

`SessionStore.create()` is designed to create a new session (i.e. one not
loaded from the session store and with `session_key=None`). `save()` is
designed to save an existing session (i.e. one loaded from the session store).
Calling `save()` on a new session may also work but has a small chance of
generating a `session_key` that collides with an existing one. `create()`
calls `save()` and loops until an unused `session_key` is generated.

If you're using the `django.contrib.sessions.backends.db` backend, each
session is a normal Django model. The `Session` model is defined in
[django/contrib/sessions/models.py](https://github.com/django/django/blob/stable/6.1.x/django/contrib/sessions/models.py). Because it's a normal model, you
can access sessions using the normal Django database API:

```pycon
>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk="2b1189a188b44ad18c35e113ac6ceead")
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)
```

Note that you'll need to call
[`get_decoded()`](#django.contrib.sessions.base_session.AbstractBaseSession.get_decoded) to get the session
dictionary. This is necessary because the dictionary is stored in an encoded
format:

```pycon
>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}
```

## When sessions are saved

By default, Django only saves to the session database when the session has been
modified -- that is if any of its dictionary values have been assigned or
deleted:

```
# Session is modified.
request.session["foo"] = "bar"

# Session is modified.
del request.session["foo"]

# Session is modified.
request.session["foo"] = {}

# Gotcha: Session is NOT modified, because this alters
# request.session['foo'] instead of request.session.
request.session["foo"]["bar"] = "baz"
```

In the last case of the above example, we can tell the session object
explicitly that it has been modified by setting the `modified` attribute on
the session object:

```
request.session.modified = True
```

To change this default behavior, set the [`SESSION_SAVE_EVERY_REQUEST`](/ga/6.1/ref/settings/#std-setting-SESSION_SAVE_EVERY_REQUEST)
setting to `True`. When set to `True`, Django will save the session to the
database on every single request.

Note that the session cookie is only sent when a session has been created or
modified. If [`SESSION_SAVE_EVERY_REQUEST`](/ga/6.1/ref/settings/#std-setting-SESSION_SAVE_EVERY_REQUEST) is `True`, the session
cookie will be sent on every request.

Similarly, the `expires` part of a session cookie is updated each time the
session cookie is sent.

The session is not saved if the response's status code is 500.

## Browser-length sessions vs. persistent sessions

You can control whether the session framework uses browser-length sessions vs.
persistent sessions with the [`SESSION_EXPIRE_AT_BROWSER_CLOSE`](/ga/6.1/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE)
setting.

By default, [`SESSION_EXPIRE_AT_BROWSER_CLOSE`](/ga/6.1/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE) is set to `False`,
which means session cookies will be stored in users' browsers for as long as
[`SESSION_COOKIE_AGE`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_AGE). Use this if you don't want people to have to
log in every time they open a browser.

If [`SESSION_EXPIRE_AT_BROWSER_CLOSE`](/ga/6.1/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE) is set to `True`, Django will
use browser-length cookies -- cookies that expire as soon as the user closes
their browser. Use this if you want people to have to log in every time they
open a browser.

This setting is a global default and can be overwritten at a per-session level
by explicitly calling the [`set_expiry()`](#django.contrib.sessions.backends.base.SessionBase.set_expiry) method
of `request.session` as described above in [using sessions in views](#using-sessions-in-views).

> **Note**
>
> Some browsers (Chrome, for example) provide settings that allow users to
> continue browsing sessions after closing and reopening the browser. In
> some cases, this can interfere with the
> [`SESSION_EXPIRE_AT_BROWSER_CLOSE`](/ga/6.1/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE) setting and prevent sessions
> from expiring on browser close. Please be aware of this while testing
> Django applications which have the
> [`SESSION_EXPIRE_AT_BROWSER_CLOSE`](/ga/6.1/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE) setting enabled.

## Clearing the session store

As users create new sessions on your website, session data can accumulate in
your session store. If you're using the database backend, the
`django_session` database table will grow. If you're using the file backend,
your temporary directory will contain an increasing number of files.

To understand this problem, consider what happens with the database backend.
When a user logs in, Django adds a row to the `django_session` database
table. Django updates this row each time the session data changes. If the user
logs out manually, Django deletes the row. But if the user does *not* log out,
the row never gets deleted. A similar process happens with the file backend.

Django does *not* provide automatic purging of expired sessions. Therefore,
it's your job to purge expired sessions on a regular basis. Django provides a
clean-up management command for this purpose: [`clearsessions`](/ga/6.1/ref/django-admin/#django-admin-clearsessions). It's
recommended to call this command on a regular basis, for example as a daily
cron job.

Note that the cache backend isn't vulnerable to this problem, because caches
automatically delete stale data. Neither is the cookie backend, because the
session data is stored by the users' browsers.

## Socruithe

A few [Django settings](/ga/6.1/ref/settings/#settings-sessions) give you control over session
behavior:

- [`SESSION_CACHE_ALIAS`](/ga/6.1/ref/settings/#std-setting-SESSION_CACHE_ALIAS)
- [`SESSION_COOKIE_AGE`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_AGE)
- [`SESSION_COOKIE_DOMAIN`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_DOMAIN)
- [`SESSION_COOKIE_HTTPONLY`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_HTTPONLY)
- [`SESSION_COOKIE_NAME`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_NAME)
- [`SESSION_COOKIE_PATH`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_PATH)
- [`SESSION_COOKIE_SAMESITE`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_SAMESITE)
- [`SESSION_COOKIE_SECURE`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_SECURE)
- [`SESSION_ENGINE`](/ga/6.1/ref/settings/#std-setting-SESSION_ENGINE)
- [`SESSION_EXPIRE_AT_BROWSER_CLOSE`](/ga/6.1/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE)
- [`SESSION_FILE_PATH`](/ga/6.1/ref/settings/#std-setting-SESSION_FILE_PATH)
- [`SESSION_SAVE_EVERY_REQUEST`](/ga/6.1/ref/settings/#std-setting-SESSION_SAVE_EVERY_REQUEST)
- [`SESSION_SERIALIZER`](/ga/6.1/ref/settings/#std-setting-SESSION_SERIALIZER)

## Session security

Subdomains within a site are able to set cookies on the client for the whole
domain. This makes session fixation possible if cookies are permitted from
subdomains not controlled by trusted users.

For example, an attacker could log into `good.example.com` and get a valid
session for their account. If the attacker has control over
`bad.example.com`, they can use it to send their session key to you since a
subdomain is permitted to set cookies on `*.example.com`. When you visit
`good.example.com`, you'll be logged in as the attacker and might
inadvertently enter your sensitive personal data (e.g. credit card info) into
the attacker's account.

Another possible attack would be if `good.example.com` sets its
[`SESSION_COOKIE_DOMAIN`](/ga/6.1/ref/settings/#std-setting-SESSION_COOKIE_DOMAIN) to `"example.com"` which would cause
session cookies from that site to be sent to `bad.example.com`.

## Technical details

- The session dictionary accepts any [`json`](https://docs.python.org/3/library/json.html#module-json) serializable value when using
  [`JSONSerializer`](#django.contrib.sessions.serializers.JSONSerializer).
- Session data is stored in a database table named `django_session` .
- Django only sends a cookie if it needs to. If you don't set any session
  data, it won't send a session cookie.

### The `SessionStore` object

When working with sessions internally, Django uses a session store object from
the corresponding session engine. By convention, the session store object class
is named `SessionStore` and is located in the module designated by
[`SESSION_ENGINE`](/ga/6.1/ref/settings/#std-setting-SESSION_ENGINE).

All `SessionStore` subclasses available in Django implement the following
data manipulation methods:

- ann () \`\`
- cruthaigh () \`\`
- `save()`
- scrios () \`\`
- `load()`
- [`clear_expired()`](#django.contrib.sessions.backends.base.SessionBase.clear_expired)

An asynchronous interface for these methods is provided by wrapping them with
`sync_to_async()`. They can be implemented directly if an async-native
implementation is available:

- `aexists()`
- `acreate()`
- `asave()`
- `adelete()`
- `aload()`
- [`aclear_expired()`](#django.contrib.sessions.backends.base.SessionBase.aclear_expired)

In order to build a custom session engine or to customize an existing one, you
may create a new class inheriting from [`SessionBase`](#django.contrib.sessions.backends.base.SessionBase) or
any other existing `SessionStore` class.

You can extend the session engines, but doing so with database-backed session
engines generally requires some extra effort (see the next section for
details).

## Extending database-backed session engines

Creating a custom database-backed session engine built upon those included in
Django (namely `db` and `cached_db`) may be done by inheriting
[`AbstractBaseSession`](#django.contrib.sessions.base_session.AbstractBaseSession) and either `SessionStore` class.

`AbstractBaseSession` and `BaseSessionManager` are importable from
`django.contrib.sessions.base_session` so that they can be imported without
including `django.contrib.sessions` in [`INSTALLED_APPS`](/ga/6.1/ref/settings/#std-setting-INSTALLED_APPS).

#### `class base_session.AbstractBaseSession`

The abstract base session model.

#### `session_key`

Primary key. The field itself may contain up to 40 characters. The
current implementation generates a 32-character string (a random
sequence of digits and lowercase ASCII letters).

#### `session_data`

A string containing an encoded and serialized session dictionary.

#### `expire_date`

A datetime designating when the session expires.

Expired sessions are not available to a user, however, they may still
be stored in the database until the [`clearsessions`](/ga/6.1/ref/django-admin/#django-admin-clearsessions) management
command is run.

#### `classmethod get_session_store_class()`

Returns a session store class to be used with this session model.

#### `get_decoded()`

Returns decoded session data.

Decoding is performed by the session store class.

You can also customize the model manager by subclassing
[`BaseSessionManager`](#django.contrib.sessions.base_session.BaseSessionManager):

#### `class base_session.BaseSessionManager`

#### `encode(session_dict)`

Returns the given session dictionary serialized and encoded as a
string.

Encoding is performed by the session store class tied to a model class.

#### `save(session_key, session_dict, expire_date)`

Saves session data for a provided session key, or deletes the session
in case the data is empty.

Customization of `SessionStore` classes is achieved by overriding methods
and properties described below:

#### `class backends.db.SessionStore`

Implements database-backed session store.

#### `classmethod get_model_class()`

Override this method to return a custom session model if you need one.

#### `create_model_instance(data)`

Returns a new instance of the session model object, which represents
the current session state.

Overriding this method provides the ability to modify session model
data before it's saved to database.

#### `class backends.cached_db.SessionStore`

Implements cached database-backed session store.

#### `cache_key_prefix`

A prefix added to a session key to build a cache key string.

### Sampla

The example below shows a custom database-backed session engine that includes
an additional database column to store an account ID (thus providing an option
to query the database for all active sessions for an account):

```
from django.contrib.sessions.backends.db import SessionStore as DBStore
from django.contrib.sessions.base_session import AbstractBaseSession
from django.db import models

class CustomSession(AbstractBaseSession):
    account_id = models.IntegerField(null=True, db_index=True)

    @classmethod
    def get_session_store_class(cls):
        return SessionStore

class SessionStore(DBStore):
    @classmethod
    def get_model_class(cls):
        return CustomSession

    def create_model_instance(self, data):
        obj = super().create_model_instance(data)
        try:
            account_id = int(data.get("_auth_user_id"))
        except (ValueError, TypeError):
            account_id = None
        obj.account_id = account_id
        return obj
```

If you are migrating from the Django's built-in `cached_db` session store to
a custom one based on `cached_db`, you should override the cache key prefix
in order to prevent a namespace clash:

```
class SessionStore(CachedDBStore):
    cache_key_prefix = "mysessions.custom_cached_db_backend"

    # ...
```

## Session IDs in URLs

The Django sessions framework is entirely, and solely, cookie-based. It does
not fall back to putting session IDs in URLs as a last resort, as PHP does.
This is an intentional design decision. Not only does that behavior make URLs
ugly, it makes your site vulnerable to session-ID theft via the "Referer"
header.
