-
Notifications
You must be signed in to change notification settings - Fork 4
Django model mixin to ease stashing objects in the session (eg for deferred registration/login)
License
jaylett/django_session_stashable
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
======================== django_session_stashable ======================== Django model mixin that makes it easy to manage a list of objects associated with the current session, principally for the purposes of implementing deferred registration. I've written a more detailed walkthrough that may be of interest: <https://tartarus.org/james/diary/2009/07/24/implementing-deferred-registration-with-django>. This was derived from code I wrote at a <https://devfort.com/>. Basic use ========= ---------------------------------------------------------------------------- from django.db import models from django.contrib.auth.models import User from django_session_stashable import SessionStashable class MyModel(models.Model, SessionStashable): created_by = models.ForeignKey(User, null=True) name = models.CharField(max_length=255) def __unicode__(self): return self.name ---------------------------------------------------------------------------- Then you can push an object into the session during a view function: ---------------------------------------------------------------------------- obj = MyModel(name="name") obj.save() obj.stash_in_session(request.session) ---------------------------------------------------------------------------- Note that you must save the object to the database; django_session_stashable records the object's pk. You can retrieve a queryset of objects using a class method: ---------------------------------------------------------------------------- stashed_objects = MyModel.get_stashed_in_session(request.session) ---------------------------------------------------------------------------- Checking whether a given object is stashed ========================================== You can check whether an object is stashed in the current session: ---------------------------------------------------------------------------- if obj.stashed_in_session(request.session): ... ---------------------------------------------------------------------------- This will often be used in authorization checks; either you only want to check that, or more commonly you combine it with a check against the creating user. Something like the following: ---------------------------------------------------------------------------- class MyModel(models.Model, SessionStashable): def visible_by_this_request(self, request): if self.created_by==None: return self.stashed_in_session(request.session) else: return self.created_by == request.user ---------------------------------------------------------------------------- Checking whether any objects are stashed ======================================== If implementing deferred registration, you may want a prominent warning that there are "unsaved" objects attached to the session, encouraging registration (or login) after your users have created something in the system. ---------------------------------------------------------------------------- if MyModel.num_stashed_in_session(request.session): ... ---------------------------------------------------------------------------- Most commonly, you'll pass that number to your template to switch on a warning block. To make this easy, there's a context processor you can pull in, `django_session_stashable.stashed_object_counts`; you'll need to set `context_count_name` on each stashable model, and the count will appear in the context as that name. Deferred registration and login =============================== While you could write a function to find all the objects in the session and mark them as belonging to the new user, it's easier just to call the supplied class method: ---------------------------------------------------------------------------- MyModel.reparent_all_my_session_objects(request.session, user) ---------------------------------------------------------------------------- Note that this assumes that you mark object creation using a created_by field, as in the previous example, or you have set the `creator_field` on your class (see example below). The `reparent_all_session_objects` function is provided as a convenience; connect it to the `django.contrib.auth.singals.user_logged_in` signal to reparent all stashed objects for all models that inherit from SessionStashable when a user logs in: ---------------------------------------------------------------------------- from django.contrib import auth from django_session_stashable import reparent_all_session_objects auth.signals.user_logged_in.connect(reparent_all_session_objects) ---------------------------------------------------------------------------- Getting all objects, whether stashed or owned by a real user ============================================================ As a convenience, there is a class method get_objects_for_request which will return either all objects owned by the authenticated user, or all objects stashed in the session, in that order: ---------------------------------------------------------------------------- def list_view(request): return render( request, 'template.html', { 'objects': MyModel.get_objects_for_request(request), }, ) ---------------------------------------------------------------------------- There is an assumption that MyModel.objects.filter(...) is the right way to go here; if that isn't true for your app, the code isn't complicated: this simply saves time. Internals ========= We store against the session, by default using the key "object_stash". If you don't want to use this, or you want to stash objects of different types against the session, you can change the session_variable setting on your class: ---------------------------------------------------------------------------- class MyModel(models.Model, SessionStashable): session_variable = 'mymodel_stash' created_by = models.ForeignKey(User) name = models.CharField(max_length=255) class MySecondModel(models.Model, SessionStashable): session_variable = 'mysecondmodel_stash' created_by = models.ForeignKey(User) name = models.CharField(max_length=255) ---------------------------------------------------------------------------- We assume the field that stores the creator is called created_by, but you can change this by setting the creator_field on your class: ---------------------------------------------------------------------------- class MyModel(models.Model, SessionStashable): session_variable = 'mymodel_stash' creator_field = 'creator' creator = models.ForeignKey(User) name = models.CharField(max_length=255) ---------------------------------------------------------------------------- (These two settings would probably benefit from being turned into Meta attributes or similar, but for now I can't be bothered to figure out the nicest approach.) James Aylett <https://tartarus.org/james/computers/django/>
About
Django model mixin to ease stashing objects in the session (eg for deferred registration/login)
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published