-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathREADME
146 lines (103 loc) · 6.67 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
========================
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: <http://tartarus.org/james/diary/2009/07/24/implementing-deferred-registration-with-django>.
This was derived from code I wrote at a <http://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 <http://tartarus.org/james/computers/django/>