Extended session backends for Django (Sessions store IP, User Agent, and foreign key to User)
django-qsessions offers two extended session backends for Django.
They extend Django's db
and cached_db
backends (and Session
model)
with following extra features:
These features help you implement "Session Management" and show a list of active sessions to the user. You can display IP, location and user agent for each session and add an option to revoke sessions.
Here is a brief comparison between Django's session backends (db, cache, cached_db), and django-qsessions.
django | qsessions | ||||
---|---|---|---|---|---|
cache | db | cached_db | db | cached_db | |
Performance | ✔✔ | ✔ | ✔ | ||
Persistence | ✔ | ✔ | ✔ | ✔ | |
Foreign Key to User | ✔ | ✔ | |||
Store IP and User Agent | ✔ | ✔ |
If your system is in production and there are active sessions using another session backend, you need to migrate them manually. We have no migration script.
If you want to use the cached_db
backend, make sure you've
configured your
cache. If you
have multiple caches defined in CACHES
, Django will use the
default cache. To use another cache, set SESSION_CACHE_ALIAS
to
the name of that cache.
Install the latest version from PyPI:
pip install django-qsessions
In settings:
INSTALLED_APPS
replace 'django.contrib.sessions'
with
'qsessions'
.MIDDLEWARE
or MIDDLEWARE_CLASSES
replace
'django.contrib.sessions.middleware.SessionMiddleware'
with
'qsessions.middleware.SessionMiddleware'
.SESSION_ENGINE
to:
'qsessions.backends.cached_db'
if you want to use
cached_db
backend.'qsessions.backends.db'
if you want to use db
backend.Run migrations to create qsessions.models.Session
model.
python manage.py migrate qsessions
To enable location detection using GeoIP2 (optional):
Install geoip2
package:
pip install geoip2
Set GEOIP_PATH
to a directory for storing GeoIP2 database.
Run the following command to download latest GeoIP2 database. You
can add this command to a cron job to update GeoIP2 DB
automatically. Due to Maxmind license
changes
you will need to acquire and use a license key for downloading the
databases. You can pass the key on the command line, or in the
MAXMIND_LICENSE_KEY
environment variable.
python manage.py download_geoip_db -k mykey
django-qsessions has a custom Session
model with following extra
fields: user
, user_agent
, created_at
, updated_at
, ip
.
Get a user's sessions:
user.session_set.filter(expire_date__gt=timezone.now())
Delete a session:
# Deletes the session from both the database and the cache.
session.delete()
Logout a user:
user.session_set.all().delete()
Get session creation time (user login time):
>>> session.created_at
datetime.datetime(2018, 6, 12, 17, 9, 17, 443909, tzinfo=<UTC>)
Get IP and user agent:
>>> session.ip
'127.0.0.1'
>>> session.user_agent
'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Mobile Safari/537.36'
Get user device (parsed user-agent string):
>>> str(session.device())
'K / Android 10 / Chrome Mobile 118.0.0'
>>> session.device().device
Device(family='K', brand='Generic_Android', model='K')
>>> session.device().os
OperatingSystem(family='Android', version=(10,), version_string='10')
>>> session.device().browser
Browser(family='Chrome Mobile', version=(118, 0, 0), version_string='118.0.0')
And if you have configured GeoIP2, you can get location info using .location()
and .location_info()
:
>>> session.location()
'Tehran, Iran'
>>> session.location_info()
{'city': 'Tehran', 'continent_code': 'AS', 'continent_name': 'Asia', 'country_code': 'IR', 'country_name': 'Iran', 'time_zone': 'Asia/Tehran', ...}
Admin page:
session.updated_at
is not the session's exact last activity. It's
updated each time the session object in DB is saved. (e.g. when user
logs in, or when ip, user agent, or session data changes)django-user-sessions
?django-user-sessions
has the same functionality, but only extends the db
backend. Using a
cache can improve performance.
We got ideas and some codes from django-user-sessions. Many thanks to Bouke Haarsma for writing django-user-sessions.
pip install -e '.[dev]'
pre-commit install
py.test --cov
cached_db
)Contributions are welcome!
MIT