forked from jaylett/django_session_stashable
-
Notifications
You must be signed in to change notification settings - Fork 0
Django model mixin to ease stashing objects in the session (eg for deferred registration/login)
License
duncanparkes/django_session_stashable
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) 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. 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) ---------------------------------------------------------------------------- If you want to do more Note that this assumes that you mark object creation using a created_by field, as in the previous example. I always do this, for consistency, but if you prefer to call it something else, you can do the work yourself using other provided functions. Say you called the field creator instead: ---------------------------------------------------------------------------- for obj in MyModel.get_stashed_in_session(request.session): obj.creator = user obj.save() MyModel.clear_stashed_objects(request.session) ---------------------------------------------------------------------------- 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
Languages
- Python 100.0%