Skip to content
Newer
Older
100644 222 lines (137 sloc) 8.08 KB
5b51166 @kennethlove readme
kennethlove authored
1 Here are the generic mixins we've been using a lot lately. If you have any that you find useful, feel free to send them to us in a pull request. Please include example usage.
2
3 .. contents:: Mixins
4 :depth: 1
5 :class: well
6
7
8 LoginRequiredMixin
9 ==================
10
11 This mixin is rather simple and is generally the first inherited class in any of our views. If we don't have an authenticated user
12 there's no need to go any further. If you've used Django before you are probably familiar with the ``login_required`` decorator.
13 All we are doing here is requiring a user to be authenticated to be able to get to this view.
14
15 While this doesn't look like much, it frees us up from having to manually overload the dispatch method on every single view that
16 requires a user to be authenticated. If that's all that is needed on this view, we just saved 3 lines of code. Example usage below.
17
b573a69 @kennethlove updated readme
kennethlove authored
18 ::
5b51166 @kennethlove readme
kennethlove authored
19
20 from django.views.generic import TemplateView
21
22 from braces.views import LoginRequiredMixin
23
24
25 class SomeSecretView(LoginRequiredMixin, TemplateView):
26 template_name = "path/to/template.html"
27
28 def get(self, request):
29 return self.render_to_response({})
30
31
32 PermissionRequiredMixin
33 =======================
34
35 This mixin was originally written, I believe, by `Daniel Sokolowski`_ (`code here`_), but we have updated it to eliminate an unneeded render if the permissions check fails.
36
37 The permission required mixin has been very handy for our client's custom CMS. Again, rather than overloading the
38 dispatch method manually on every view that needs to check for the existence of a permission, we inherit this class
39 and set the ``permission_required`` class attribute on our view. If you don't specify ``permission_required`` on
40 your view, an ``ImproperlyConfigured`` exception is raised reminding you that you haven't set it.
41
42 The one limitation of this mixin is that it can **only** accept a single permission. It would need to be modified to
43 handle more than one. We haven't needed that yet, so this has worked out well for us.
44
45 In our normal use case for this mixin, ``LoginRequiredMixin`` comes first, then the ``PermissionRequiredMixin``. If we
46 don't have an authenticated user, there is no sense in checking for any permissions.
47
48 .. role:: info-label
49 :class: "label label-info"
50
51 :info-label:`note` If you are using Django's built in auth system, ``superusers`` automatically have all permissions in your system.
52
b573a69 @kennethlove updated readme
kennethlove authored
53 ::
5b51166 @kennethlove readme
kennethlove authored
54
55 from braces.views import LoginRequiredMixin, PermissionRequiredMixin
56
57
58 class SomeProtectedView(LoginRequiredMixin, PermissionRequiredMixin, TemplateView):
59 permission_required = "auth.change_user"
60 template_name = "path/to/template.html"
61
62 SuperuserRequiredMixin
63 ======================
64
65 Another permission-based mixin. This is specifically for requiring a user to be a superuser. Comes in handy for tools that only privileged
66 users should have access to.
67
b573a69 @kennethlove updated readme
kennethlove authored
68 ::
5b51166 @kennethlove readme
kennethlove authored
69
70 from braces.views import LoginRequiredMixin, SuperuserRequiredMixin
71
72
73 class SomeSuperuserView(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
74 template_name = "path/to/template.html"
75
76 UserFormKwargsMixin
77 ===================
78
79 In our clients CMS, we have a lot of form-based views that require a user to be passed in for permission-based form tools. For example,
80 only superusers can delete or disable certain objects. To custom tailor the form for users, we have to pass that user instance into the form
81 and based on their permission level, change certain fields or add specific options within the forms ``__init__`` method.
82
83 This mixin automates the process of overloading the ``get_form_kwargs`` (this method is available in any generic view which handles a form) method
84 and stuffs the user instance into the form kwargs. We can then pop the user off in the form and do with it what we need. **Always** remember
85 to pop the user from the kwargs before calling ``super`` on your form, otherwise the form gets an unexpected keyword argument and everything
86 blows up. Example usage:
87
b573a69 @kennethlove updated readme
kennethlove authored
88 ::
5b51166 @kennethlove readme
kennethlove authored
89
90 from django.views.generic import CreateView
91
92 from braces.views import LoginRequiredMixin, UserFormKwargsMixin
93 from next.example import UserForm
94
95
96 class SomeSecretView(LoginRequiredMixin, UserFormKwargsMixin,
97 TemplateView):
98
99 form_class = UserForm
100 model = User
101 template_name = "path/to/template.html"
102
103 This obviously pairs very nicely with the following ``Form`` mixin.
104
105
106 UserKwargModelFormMixin
107 =======================
108
109 The ``UserKwargModelFormMixin`` is a new form mixin we just implemented this week to go along with our ``UserFormKwargsMixin``.
110 This becomes the first inherited class of our forms that receive the user keyword argument. With this mixin, we have automated
111 the popping off of the keyword argument in our form and no longer have to do it manually on every form that works this way.
112 While this may be overkill for a weekend project, for us, it speeds up adding new features. Example usage:
113
b573a69 @kennethlove updated readme
kennethlove authored
114 ::
5b51166 @kennethlove readme
kennethlove authored
115
116 from braces.forms import UserKwargModelFormMixin
117
118
119 class UserForm(UserKwargModelFormMixin, forms.ModelForm):
120 class Meta:
121 model = User
122
123 def __init__(self, *args, **kwargs):
124 super(UserForm, self).__init__(*args, **kwargs):
125
126 if not self.user.is_superuser:
127 del self.fields["group"]
128
129
130 SuccessURLRedirectListMixin
131 ===========================
132
133 The ``SuccessURLRedirectListMixin`` is a bit more tailored to how we handle CRUD_ within our CMS. Our CMS's workflow, by design,
134 redirects the user to the ``ListView`` for whatever model they are working with, whether they are creating a new instance, editing
135 an existing one or deleting one. Rather than having to override ``get_success_url`` on every view, we simply use this mixin and pass it
136 a reversible route name. Example:
137
b573a69 @kennethlove updated readme
kennethlove authored
138 ::
5b51166 @kennethlove readme
kennethlove authored
139
140 # urls.py
141 url(r"^users/$", UserListView.as_view(), name="cms_users_list"),
142
143 # views.py
144 from braces.views import (LoginRequiredMixin, PermissionRequiredMixin,
145 SuccessURLRedirectListMixin)
146
147
148 class UserCreateView(LoginRequiredMixin, PermissionRequiredMixin,
149 SuccessURLRedirectListMixin, CreateView):
150
151 form_class = UserForm
152 model = User
153 permission_required = "auth.add_user"
154 success_list_url = "cms_users_list"
155 ...
156
157
158 SetHeadlineMixin
159 ================
160
161 The ``SetHeadlineMixin`` is a newer edition to our client's CMS. It allows us to *statically* or *programmatically* set the headline of any
162 of our views. We like to write as few templates as possible, so a mixin like this helps us reuse generic templates. Its usage is amazingly
163 straightforward and works much like Django's built-in ``get_queryset`` method. This mixin has two ways of being used.
164
165 Static Example
166 --------------
167
b573a69 @kennethlove updated readme
kennethlove authored
168 ::
5b51166 @kennethlove readme
kennethlove authored
169
170 from braces.views import SetHeadlineMixin
171
172
173 class HeadlineView(SetHeadlineMixin, TemplateView):
174 headline = "This is our headline"
175 template_name = "path/to/template.html"
176
177
178 Dynamic Example
179 ---------------
180
b573a69 @kennethlove updated readme
kennethlove authored
181 ::
5b51166 @kennethlove readme
kennethlove authored
182
183 from datetime import date
184
185 from braces.views import SetHeadlineMixin
186
187
188 class HeadlineView(SetHeadlineMixin, TemplateView):
189 template_name = "path/to/template.html"
190
191 def get_headline(self):
192 return u"This is our headline for %s" % date.today().isoformat()
193
194 In both usages, in the template, just print out ``{{ headline }}`` to show the generated headline.
195
196
197 CreateAndRedirectToEditView
198 ===========================
199
200 Mostly used for CRUD, where you're going to create an object and then move direct to the update view for that object. Your URL for the update view has to accept a PK for the object.
201
b573a69 @kennethlove updated readme
kennethlove authored
202 ::
5b51166 @kennethlove readme
kennethlove authored
203
204 # urls.py
205 ...
206 url(r"^users/create/$", UserCreateView.as_view(), name="cms_users_create"),
207 url(r"^users/edit/(?P<pk>\d+)/$", UserUpdateView.as_view(), name="cms_users_update"),
208 ...
209
210 # views.py
211 from braces.views import CreateAndRedirectToEditView
212
213
214 class UserCreateView(CreateAndRedirectToEditView, CreateView):
215 model = User
216 ...
217
218
219 .. _Daniel Sokolowski: https://github.com/danols
220 .. _code here: https://github.com/lukaszb/django-guardian/issues/48
221 .. _CRUD: http://en.wikipedia.org/wiki/Create,_read,_update_and_delete
Something went wrong with that request. Please try again.