|
1 =================== |
|
2 How to use sessions |
|
3 =================== |
|
4 |
|
5 .. module:: django.contrib.sessions |
|
6 :synopsis: Provides session management for Django projects. |
|
7 |
|
8 Django provides full support for anonymous sessions. The session framework lets |
|
9 you store and retrieve arbitrary data on a per-site-visitor basis. It stores |
|
10 data on the server side and abstracts the sending and receiving of cookies. |
|
11 Cookies contain a session ID -- not the data itself. |
|
12 |
|
13 Enabling sessions |
|
14 ================= |
|
15 |
|
16 Sessions are implemented via a piece of :doc:`middleware </ref/middleware>`. |
|
17 |
|
18 To enable session functionality, do the following: |
|
19 |
|
20 * Edit the ``MIDDLEWARE_CLASSES`` setting and make sure |
|
21 ``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``. |
|
22 The default ``settings.py`` created by ``django-admin.py startproject`` has |
|
23 ``SessionMiddleware`` activated. |
|
24 |
|
25 If you don't want to use sessions, you might as well remove the |
|
26 ``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'`` |
|
27 from your ``INSTALLED_APPS``. It'll save you a small bit of overhead. |
|
28 |
|
29 Configuring the session engine |
|
30 ============================== |
|
31 |
|
32 .. versionadded:: 1.0 |
|
33 |
|
34 By default, Django stores sessions in your database (using the model |
|
35 ``django.contrib.sessions.models.Session``). Though this is convenient, in |
|
36 some setups it's faster to store session data elsewhere, so Django can be |
|
37 configured to store session data on your filesystem or in your cache. |
|
38 |
|
39 Using database-backed sessions |
|
40 ------------------------------ |
|
41 |
|
42 If you want to use a database-backed session, you need to add |
|
43 ``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting. |
|
44 |
|
45 Once you have configured your installation, run ``manage.py syncdb`` |
|
46 to install the single database table that stores session data. |
|
47 |
|
48 Using cached sessions |
|
49 --------------------- |
|
50 |
|
51 For better performance, you may want to use a cache-based session backend. |
|
52 |
|
53 .. versionchanged:: 1.1 |
|
54 Django 1.0 did not include the ``cached_db`` session backend. |
|
55 |
|
56 To store session data using Django's cache system, you'll first need to make |
|
57 sure you've configured your cache; see the :doc:`cache documentation |
|
58 </topics/cache>` for details. |
|
59 |
|
60 .. warning:: |
|
61 |
|
62 You should only use cache-based sessions if you're using the Memcached |
|
63 cache backend. The local-memory cache backend doesn't retain data long |
|
64 enough to be a good choice, and it'll be faster to use file or database |
|
65 sessions directly instead of sending everything through the file or |
|
66 database cache backends. |
|
67 |
|
68 Once your cache is configured, you've got two choices for how to store data in |
|
69 the cache: |
|
70 |
|
71 * Set :setting:`SESSION_ENGINE` to |
|
72 ``"django.contrib.sessions.backends.cache"`` for a simple caching session |
|
73 store. Session data will be stored directly your cache. However, session |
|
74 data may not be persistent: cached data can be evicted if the cache fills |
|
75 up or if the cache server is restarted. |
|
76 |
|
77 * For persistent, cached data, set :setting:`SESSION_ENGINE` to |
|
78 ``"django.contrib.sessions.backends.cached_db"``. This uses a |
|
79 write-through cache -- every write to the cache will also be written to |
|
80 the database. Session reads only use the database if the data is not |
|
81 already in the cache. |
|
82 |
|
83 Both session stores are quite fast, but the simple cache is faster because it |
|
84 disregards persistence. In most cases, the ``cached_db`` backend will be fast |
|
85 enough, but if you need that last bit of performance, and are willing to let |
|
86 session data be expunged from time to time, the ``cache`` backend is for you. |
|
87 |
|
88 If you use the ``cached_db`` session backend, you also need to follow the |
|
89 configuration instructions for the `using database-backed sessions`_. |
|
90 |
|
91 Using file-based sessions |
|
92 ------------------------- |
|
93 |
|
94 To use file-based sessions, set the ``SESSION_ENGINE`` setting to |
|
95 ``"django.contrib.sessions.backends.file"``. |
|
96 |
|
97 You might also want to set the ``SESSION_FILE_PATH`` setting (which defaults |
|
98 to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to control |
|
99 where Django stores session files. Be sure to check that your Web server has |
|
100 permissions to read and write to this location. |
|
101 |
|
102 |
|
103 Using sessions in views |
|
104 ======================= |
|
105 |
|
106 When ``SessionMiddleware`` is activated, each ``HttpRequest`` object -- the |
|
107 first argument to any Django view function -- will have a ``session`` |
|
108 attribute, which is a dictionary-like object. You can read it and write to it. |
|
109 |
|
110 A session object has the following standard dictionary methods: |
|
111 |
|
112 * ``__getitem__(key)`` |
|
113 |
|
114 Example: ``fav_color = request.session['fav_color']`` |
|
115 |
|
116 * ``__setitem__(key, value)`` |
|
117 |
|
118 Example: ``request.session['fav_color'] = 'blue'`` |
|
119 |
|
120 * ``__delitem__(key)`` |
|
121 |
|
122 Example: ``del request.session['fav_color']``. This raises ``KeyError`` |
|
123 if the given ``key`` isn't already in the session. |
|
124 |
|
125 * ``__contains__(key)`` |
|
126 |
|
127 Example: ``'fav_color' in request.session`` |
|
128 |
|
129 * ``get(key, default=None)`` |
|
130 |
|
131 Example: ``fav_color = request.session.get('fav_color', 'red')`` |
|
132 |
|
133 * ``keys()`` |
|
134 |
|
135 * ``items()`` |
|
136 |
|
137 * ``setdefault()`` |
|
138 |
|
139 * ``clear()`` |
|
140 |
|
141 .. versionadded:: 1.0 |
|
142 ``setdefault()`` and ``clear()`` are new in this version. |
|
143 |
|
144 It also has these methods: |
|
145 |
|
146 * ``flush()`` |
|
147 |
|
148 .. versionadded:: 1.0 |
|
149 |
|
150 Delete the current session data from the session and regenerate the |
|
151 session key value that is sent back to the user in the cookie. This is |
|
152 used if you want to ensure that the previous session data can't be |
|
153 accessed again from the user's browser (for example, the |
|
154 :func:`django.contrib.auth.logout()` function calls it). |
|
155 |
|
156 * ``set_test_cookie()`` |
|
157 |
|
158 Sets a test cookie to determine whether the user's browser supports |
|
159 cookies. Due to the way cookies work, you won't be able to test this |
|
160 until the user's next page request. See `Setting test cookies`_ below for |
|
161 more information. |
|
162 |
|
163 * ``test_cookie_worked()`` |
|
164 |
|
165 Returns either ``True`` or ``False``, depending on whether the user's |
|
166 browser accepted the test cookie. Due to the way cookies work, you'll |
|
167 have to call ``set_test_cookie()`` on a previous, separate page request. |
|
168 See `Setting test cookies`_ below for more information. |
|
169 |
|
170 * ``delete_test_cookie()`` |
|
171 |
|
172 Deletes the test cookie. Use this to clean up after yourself. |
|
173 |
|
174 * ``set_expiry(value)`` |
|
175 |
|
176 .. versionadded:: 1.0 |
|
177 |
|
178 Sets the expiration time for the session. You can pass a number of |
|
179 different values: |
|
180 |
|
181 * If ``value`` is an integer, the session will expire after that |
|
182 many seconds of inactivity. For example, calling |
|
183 ``request.session.set_expiry(300)`` would make the session expire |
|
184 in 5 minutes. |
|
185 |
|
186 * If ``value`` is a ``datetime`` or ``timedelta`` object, the |
|
187 session will expire at that specific date/time. |
|
188 |
|
189 * If ``value`` is ``0``, the user's session cookie will expire |
|
190 when the user's Web browser is closed. |
|
191 |
|
192 * If ``value`` is ``None``, the session reverts to using the global |
|
193 session expiry policy. |
|
194 |
|
195 Reading a session is not considered activity for expiration |
|
196 purposes. Session expiration is computed from the last time the |
|
197 session was *modified*. |
|
198 |
|
199 * ``get_expiry_age()`` |
|
200 |
|
201 .. versionadded:: 1.0 |
|
202 |
|
203 Returns the number of seconds until this session expires. For sessions |
|
204 with no custom expiration (or those set to expire at browser close), this |
|
205 will equal ``settings.SESSION_COOKIE_AGE``. |
|
206 |
|
207 * ``get_expiry_date()`` |
|
208 |
|
209 .. versionadded:: 1.0 |
|
210 |
|
211 Returns the date this session will expire. For sessions with no custom |
|
212 expiration (or those set to expire at browser close), this will equal the |
|
213 date ``settings.SESSION_COOKIE_AGE`` seconds from now. |
|
214 |
|
215 * ``get_expire_at_browser_close()`` |
|
216 |
|
217 .. versionadded:: 1.0 |
|
218 |
|
219 Returns either ``True`` or ``False``, depending on whether the user's |
|
220 session cookie will expire when the user's Web browser is closed. |
|
221 |
|
222 You can edit ``request.session`` at any point in your view. You can edit it |
|
223 multiple times. |
|
224 |
|
225 Session object guidelines |
|
226 ------------------------- |
|
227 |
|
228 * Use normal Python strings as dictionary keys on ``request.session``. This |
|
229 is more of a convention than a hard-and-fast rule. |
|
230 |
|
231 * Session dictionary keys that begin with an underscore are reserved for |
|
232 internal use by Django. |
|
233 |
|
234 * Don't override ``request.session`` with a new object, and don't access or |
|
235 set its attributes. Use it like a Python dictionary. |
|
236 |
|
237 Examples |
|
238 -------- |
|
239 |
|
240 This simplistic view sets a ``has_commented`` variable to ``True`` after a user |
|
241 posts a comment. It doesn't let a user post a comment more than once:: |
|
242 |
|
243 def post_comment(request, new_comment): |
|
244 if request.session.get('has_commented', False): |
|
245 return HttpResponse("You've already commented.") |
|
246 c = comments.Comment(comment=new_comment) |
|
247 c.save() |
|
248 request.session['has_commented'] = True |
|
249 return HttpResponse('Thanks for your comment!') |
|
250 |
|
251 This simplistic view logs in a "member" of the site:: |
|
252 |
|
253 def login(request): |
|
254 m = Member.objects.get(username=request.POST['username']) |
|
255 if m.password == request.POST['password']: |
|
256 request.session['member_id'] = m.id |
|
257 return HttpResponse("You're logged in.") |
|
258 else: |
|
259 return HttpResponse("Your username and password didn't match.") |
|
260 |
|
261 ...And this one logs a member out, according to ``login()`` above:: |
|
262 |
|
263 def logout(request): |
|
264 try: |
|
265 del request.session['member_id'] |
|
266 except KeyError: |
|
267 pass |
|
268 return HttpResponse("You're logged out.") |
|
269 |
|
270 The standard ``django.contrib.auth.logout()`` function actually does a bit |
|
271 more than this to prevent inadvertent data leakage. It calls |
|
272 ``request.session.flush()``. We are using this example as a demonstration of |
|
273 how to work with session objects, not as a full ``logout()`` implementation. |
|
274 |
|
275 Setting test cookies |
|
276 ==================== |
|
277 |
|
278 As a convenience, Django provides an easy way to test whether the user's |
|
279 browser accepts cookies. Just call ``request.session.set_test_cookie()`` in a |
|
280 view, and call ``request.session.test_cookie_worked()`` in a subsequent view -- |
|
281 not in the same view call. |
|
282 |
|
283 This awkward split between ``set_test_cookie()`` and ``test_cookie_worked()`` |
|
284 is necessary due to the way cookies work. When you set a cookie, you can't |
|
285 actually tell whether a browser accepted it until the browser's next request. |
|
286 |
|
287 It's good practice to use ``delete_test_cookie()`` to clean up after yourself. |
|
288 Do this after you've verified that the test cookie worked. |
|
289 |
|
290 Here's a typical usage example:: |
|
291 |
|
292 def login(request): |
|
293 if request.method == 'POST': |
|
294 if request.session.test_cookie_worked(): |
|
295 request.session.delete_test_cookie() |
|
296 return HttpResponse("You're logged in.") |
|
297 else: |
|
298 return HttpResponse("Please enable cookies and try again.") |
|
299 request.session.set_test_cookie() |
|
300 return render_to_response('foo/login_form.html') |
|
301 |
|
302 Using sessions out of views |
|
303 =========================== |
|
304 |
|
305 .. versionadded:: 1.0 |
|
306 |
|
307 An API is available to manipulate session data outside of a view:: |
|
308 |
|
309 >>> from django.contrib.sessions.backends.db import SessionStore |
|
310 >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') |
|
311 >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) |
|
312 >>> s['last_login'] |
|
313 datetime.datetime(2005, 8, 20, 13, 35, 0) |
|
314 >>> s.save() |
|
315 |
|
316 If you're using the ``django.contrib.sessions.backends.db`` backend, each |
|
317 session is just a normal Django model. The ``Session`` model is defined in |
|
318 ``django/contrib/sessions/models.py``. Because it's a normal model, you can |
|
319 access sessions using the normal Django database API:: |
|
320 |
|
321 >>> from django.contrib.sessions.models import Session |
|
322 >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') |
|
323 >>> s.expire_date |
|
324 datetime.datetime(2005, 8, 20, 13, 35, 12) |
|
325 |
|
326 Note that you'll need to call ``get_decoded()`` to get the session dictionary. |
|
327 This is necessary because the dictionary is stored in an encoded format:: |
|
328 |
|
329 >>> s.session_data |
|
330 'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...' |
|
331 >>> s.get_decoded() |
|
332 {'user_id': 42} |
|
333 |
|
334 When sessions are saved |
|
335 ======================= |
|
336 |
|
337 By default, Django only saves to the session database when the session has been |
|
338 modified -- that is if any of its dictionary values have been assigned or |
|
339 deleted:: |
|
340 |
|
341 # Session is modified. |
|
342 request.session['foo'] = 'bar' |
|
343 |
|
344 # Session is modified. |
|
345 del request.session['foo'] |
|
346 |
|
347 # Session is modified. |
|
348 request.session['foo'] = {} |
|
349 |
|
350 # Gotcha: Session is NOT modified, because this alters |
|
351 # request.session['foo'] instead of request.session. |
|
352 request.session['foo']['bar'] = 'baz' |
|
353 |
|
354 In the last case of the above example, we can tell the session object |
|
355 explicitly that it has been modified by setting the ``modified`` attribute on |
|
356 the session object:: |
|
357 |
|
358 request.session.modified = True |
|
359 |
|
360 To change this default behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting |
|
361 to ``True``. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save |
|
362 the session to the database on every single request. |
|
363 |
|
364 Note that the session cookie is only sent when a session has been created or |
|
365 modified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie |
|
366 will be sent on every request. |
|
367 |
|
368 Similarly, the ``expires`` part of a session cookie is updated each time the |
|
369 session cookie is sent. |
|
370 |
|
371 Browser-length sessions vs. persistent sessions |
|
372 =============================================== |
|
373 |
|
374 You can control whether the session framework uses browser-length sessions vs. |
|
375 persistent sessions with the ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` setting. |
|
376 |
|
377 By default, ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``False``, which |
|
378 means session cookies will be stored in users' browsers for as long as |
|
379 ``SESSION_COOKIE_AGE``. Use this if you don't want people to have to log in |
|
380 every time they open a browser. |
|
381 |
|
382 If ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``True``, Django will use |
|
383 browser-length cookies -- cookies that expire as soon as the user closes his or |
|
384 her browser. Use this if you want people to have to log in every time they open |
|
385 a browser. |
|
386 |
|
387 .. versionadded:: 1.0 |
|
388 |
|
389 This setting is a global default and can be overwritten at a per-session level |
|
390 by explicitly calling ``request.session.set_expiry()`` as described above in |
|
391 `using sessions in views`_. |
|
392 |
|
393 Clearing the session table |
|
394 ========================== |
|
395 |
|
396 If you're using the database backend, note that session data can accumulate in |
|
397 the ``django_session`` database table and Django does *not* provide automatic |
|
398 purging. Therefore, it's your job to purge expired sessions on a regular basis. |
|
399 |
|
400 To understand this problem, consider what happens when a user uses a session. |
|
401 When a user logs in, Django adds a row to the ``django_session`` database |
|
402 table. Django updates this row each time the session data changes. If the user |
|
403 logs out manually, Django deletes the row. But if the user does *not* log out, |
|
404 the row never gets deleted. |
|
405 |
|
406 Django provides a sample clean-up script: ``django-admin.py cleanup``. |
|
407 That script deletes any session in the session table whose ``expire_date`` is |
|
408 in the past -- but your application may have different requirements. |
|
409 |
|
410 Settings |
|
411 ======== |
|
412 |
|
413 A few :doc:`Django settings </ref/settings>` give you control over session behavior: |
|
414 |
|
415 SESSION_ENGINE |
|
416 -------------- |
|
417 |
|
418 .. versionadded:: 1.0 |
|
419 |
|
420 .. versionchanged:: 1.1 |
|
421 The ``cached_db`` backend was added |
|
422 |
|
423 Default: ``django.contrib.sessions.backends.db`` |
|
424 |
|
425 Controls where Django stores session data. Valid values are: |
|
426 |
|
427 * ``'django.contrib.sessions.backends.db'`` |
|
428 * ``'django.contrib.sessions.backends.file'`` |
|
429 * ``'django.contrib.sessions.backends.cache'`` |
|
430 * ``'django.contrib.sessions.backends.cached_db'`` |
|
431 |
|
432 See `configuring the session engine`_ for more details. |
|
433 |
|
434 SESSION_FILE_PATH |
|
435 ----------------- |
|
436 |
|
437 .. versionadded:: 1.0 |
|
438 |
|
439 Default: ``/tmp/`` |
|
440 |
|
441 If you're using file-based session storage, this sets the directory in |
|
442 which Django will store session data. |
|
443 |
|
444 SESSION_COOKIE_AGE |
|
445 ------------------ |
|
446 |
|
447 Default: ``1209600`` (2 weeks, in seconds) |
|
448 |
|
449 The age of session cookies, in seconds. |
|
450 |
|
451 SESSION_COOKIE_DOMAIN |
|
452 --------------------- |
|
453 |
|
454 Default: ``None`` |
|
455 |
|
456 The domain to use for session cookies. Set this to a string such as |
|
457 ``".lawrence.com"`` (note the leading dot!) for cross-domain cookies, or use |
|
458 ``None`` for a standard domain cookie. |
|
459 |
|
460 SESSION_COOKIE_NAME |
|
461 ------------------- |
|
462 |
|
463 Default: ``'sessionid'`` |
|
464 |
|
465 The name of the cookie to use for sessions. This can be whatever you want. |
|
466 |
|
467 SESSION_COOKIE_PATH |
|
468 ------------------- |
|
469 |
|
470 .. versionadded:: 1.0 |
|
471 |
|
472 Default: ``'/'`` |
|
473 |
|
474 The path set on the session cookie. This should either match the URL path of |
|
475 your Django installation or be parent of that path. |
|
476 |
|
477 This is useful if you have multiple Django instances running under the same |
|
478 hostname. They can use different cookie paths, and each instance will only see |
|
479 its own session cookie. |
|
480 |
|
481 SESSION_COOKIE_SECURE |
|
482 --------------------- |
|
483 |
|
484 Default: ``False`` |
|
485 |
|
486 Whether to use a secure cookie for the session cookie. If this is set to |
|
487 ``True``, the cookie will be marked as "secure," which means browsers may |
|
488 ensure that the cookie is only sent under an HTTPS connection. |
|
489 |
|
490 SESSION_EXPIRE_AT_BROWSER_CLOSE |
|
491 ------------------------------- |
|
492 |
|
493 Default: ``False`` |
|
494 |
|
495 Whether to expire the session when the user closes his or her browser. See |
|
496 "Browser-length sessions vs. persistent sessions" above. |
|
497 |
|
498 SESSION_SAVE_EVERY_REQUEST |
|
499 -------------------------- |
|
500 |
|
501 Default: ``False`` |
|
502 |
|
503 Whether to save the session data on every request. If this is ``False`` |
|
504 (default), then the session data will only be saved if it has been modified -- |
|
505 that is, if any of its dictionary values have been assigned or deleted. |
|
506 |
|
507 .. _Django settings: ../settings/ |
|
508 |
|
509 Technical details |
|
510 ================= |
|
511 |
|
512 * The session dictionary should accept any pickleable Python object. See |
|
513 `the pickle module`_ for more information. |
|
514 |
|
515 * Session data is stored in a database table named ``django_session`` . |
|
516 |
|
517 * Django only sends a cookie if it needs to. If you don't set any session |
|
518 data, it won't send a session cookie. |
|
519 |
|
520 .. _`the pickle module`: http://docs.python.org/library/pickle.html |
|
521 |
|
522 Session IDs in URLs |
|
523 =================== |
|
524 |
|
525 The Django sessions framework is entirely, and solely, cookie-based. It does |
|
526 not fall back to putting session IDs in URLs as a last resort, as PHP does. |
|
527 This is an intentional design decision. Not only does that behavior make URLs |
|
528 ugly, it makes your site vulnerable to session-ID theft via the "Referer" |
|
529 header. |