Skip to content

Fixed #18978 #420

Closed
wants to merge 7 commits into from
View
2 django/bin/daily_cleanup.py
@@ -10,4 +10,4 @@
from django.core import management
if __name__ == "__main__":
- management.call_command('cleanup')
+ management.call_command('cleansessions')
View
7 django/contrib/sessions/backends/base.py
@@ -281,3 +281,10 @@ def load(self):
Loads the session data and returns a dictionary.
"""
raise NotImplementedError
+
+ @classmethod
+ def cleanup(cls):
+ """
+ Cleanup the expired sessions.
+ """
+ raise NotImplementedError
View
4 django/contrib/sessions/backends/db.py
@@ -71,6 +71,10 @@ def delete(self, session_key=None):
except Session.DoesNotExist:
pass
+ @classmethod
+ def cleanup(cls):
+ Session.objects.filter(expire_date__lt=timezone.now()).delete()
+ transaction.commit_unless_managed()
# At bottom to avoid circular import
from django.contrib.sessions.models import Session
View
21 django/contrib/sessions/backends/file.py
@@ -142,3 +142,24 @@ def delete(self, session_key=None):
def clean(self):
pass
+
+ @classmethod
+ def cleanup(cls):
+ storage_path = getattr(settings, "SESSION_FILE_PATH", tempfile.gettempdir())
+ file_prefix = settings.SESSION_COOKIE_NAME
+
+ # Get all file sessions stored
+ sessions = [cls(session[len(file_prefix):])
+ for session in os.listdir(storage_path)
+ if session.startswith(file_prefix)]
+
+ for session in sessions:
+ old_key = session.session_key
+ session.load()
+ new_key = session.session_key
+
+ # The key was changed i.e. new session created, so the existing one
+ # was invalid. Lests clean it all up
+ if old_key != new_key:
+ session.delete(old_key)
+ session.delete(new_key)
View
0 django/contrib/sessions/management/__init__.py
No changes.
View
0 django/contrib/sessions/management/commands/__init__.py
No changes.
View
11 django/contrib/sessions/management/commands/cleansessions.py
@@ -0,0 +1,11 @@
+from django.core.management.base import NoArgsCommand
+from django.utils.importlib import import_module
+from django.conf import settings
+
+
+class Command(NoArgsCommand):
+ help = "Clean expired sessions."
+
+ def handle_noargs(self, **options):
+ engine = import_module(settings.SESSION_ENGINE)
+ engine.SessionStore.cleanup()
View
23 django/contrib/sessions/tests.py
@@ -12,6 +12,7 @@
from django.contrib.sessions.backends.signed_cookies import SessionStore as CookieSession
from django.contrib.sessions.models import Session
from django.contrib.sessions.middleware import SessionMiddleware
+from django.core import management
from django.core.cache import DEFAULT_CACHE_ALIAS
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.http import HttpResponse
@@ -257,6 +258,7 @@ def test_decode(self):
data = {'a test key': 'a test value'}
encoded = self.session.encode(data)
self.assertEqual(self.session.decode(encoded), data)
+
class DatabaseSessionTests(SessionTestsMixin, TestCase):
@@ -290,6 +292,27 @@ def test_sessionmanager_save(self):
del self.session._session_cache
self.assertEqual(self.session['y'], 2)
+ def test_cleansessions_command(self):
+ """
+ Test cleansessions command for cleaning expired sessions from db.
+ """
+ self.assertFalse(Session.objects.count())
+
+ # One object in the future
+ self.session['foo'] = 'bar'
+ self.session.set_expiry(timezone.now() + timedelta(hours=1))
+ self.session.save()
+
+ # One object in the past
+ self.session._session_key = None
+ self.session.set_expiry(timezone.now() - timedelta(hours=1))
+ self.session.save()
+
+ # Two sessions are in DB before clean...
+ self.assertEqual(2, Session.objects.count())
+ management.call_command('cleansessions')
+ # ... and one expired is deleted.
+ self.assertEqual(1, Session.objects.count())
@override_settings(USE_TZ=True)
class DatabaseSessionWithTimeZoneTests(DatabaseSessionTests):
View
8 django/core/management/commands/cleanup.py
@@ -1,11 +1,9 @@
+from django.core import management
from django.core.management.base import NoArgsCommand
-from django.utils import timezone
+
class Command(NoArgsCommand):
help = "Can be run as a cronjob or directly to clean out old data from the database (only expired sessions at the moment)."
def handle_noargs(self, **options):
- from django.db import transaction
- from django.contrib.sessions.models import Session
- Session.objects.filter(expire_date__lt=timezone.now()).delete()
- transaction.commit_unless_managed()
+ management.call_command('cleansessions', **options)
View
24 docs/ref/django-admin.txt
@@ -1,4 +1,7 @@
=============================
+
+
+..
django-admin.py and manage.py
=============================
@@ -93,8 +96,11 @@ cleanup
.. django-admin:: cleanup
-Can be run as a cronjob or directly to clean out old data from the database
-(only expired sessions at the moment).
+Can be run as a cronjob or directly to clean out old data from the database.
+Right now it only calls :djadmin:`cleansessions` management command from
+``django.contrib.sessions``.
+
+.. versionchanged:: 1.5
compilemessages
---------------
@@ -1199,6 +1205,20 @@ This command is only available if the :doc:`Sitemaps framework
Please refer to its :djadmin:`description <ping_google>` in the Sitemaps
documentation.
+``django.contrib.sessions``
+---------------------------
+
+cleansessions
+~~~~~~~~~~~~~
+
+This command is only available if the :doc:`Sessions </topics/http/sessions>`
+(``django.contrib.sessions``) are installed.
+
+Please refer to its :djadmin:`description <cleansessions>` in the Sessions
+documentation.
+
+.. versionadded:: 1.5
+
``django.contrib.staticfiles``
------------------------------
View
7 docs/releases/1.5.txt
@@ -452,6 +452,13 @@ with the :meth:`~django.forms.Form.is_valid()` method and not with the
presence or absence of the :attr:`~django.forms.Form.cleaned_data` attribute
on the form.
+Cleaned :djadmin:`cleanup` management command
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This command have contained only expired sessions clean up for years.
+Therefore new command :djadmin:`cleansessions` in ``django.contrib.sessions``
+do the job and :djadmin:`cleanup` command just call it.
+
Miscellaneous
~~~~~~~~~~~~~
View
33 docs/topics/http/sessions.txt
@@ -261,6 +261,11 @@ You can edit it multiple times.
Returns either ``True`` or ``False``, depending on whether the user's
session cookie will expire when the user's Web browser is closed.
+ .. method:: SessionBase.cleanup()
+
+ Class method which cleans up expired session (eg. delete related rows
+ in database, files, etc.)
+
Session object guidelines
-------------------------
@@ -460,9 +465,15 @@ 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.
-Django provides a sample clean-up script: ``django-admin.py cleanup``.
-That script deletes any session in the session table whose ``expire_date`` is
-in the past -- but your application may have different requirements.
+.. versionadded:: 1.5
+
+There is simple clean-up script in ``django-admin.py cleansessions``. That
+script deletes any session in the session table whose ``expire_date`` is in
+the past -- but your application may have different requirements.
+
+Another way is to run ``bin/daily_cleanup.py`` which clean out old data from
+the database. Only ``django-admin.py cleansessions`` command is called at
+the moment.
Settings
========
@@ -576,6 +587,22 @@ that is, if any of its dictionary values have been assigned or deleted.
.. _Django settings: ../settings/
+Management commands
+===================
+
+.. highlight:: console
+
+``django.contrib.sessions`` exposes one management commands.
+
+cleansessions
+-------------
+
+.. django-admin:: cleansessions
+
+Cleans expired sessions from database.
+
+.. versionadded:: 1.5
+
Technical details
=================
Something went wrong with that request. Please try again.