0
# Form Processing and Messaging
1
2
Mixins for enhanced form processing, validation messaging, CSRF handling, and context injection. These mixins solve common form-related challenges in Django class-based views and provide consistent user feedback patterns.
3
4
## Capabilities
5
6
### CSRF Exemption
7
8
Exempt views from CSRF protection for API endpoints and special cases.
9
10
```python { .api }
11
class CsrfExemptMixin:
12
"""Exempts the view from CSRF requirements"""
13
14
@method_decorator(csrf_exempt)
15
def dispatch(self, *args, **kwargs):
16
"""Dispatch with CSRF exemption applied"""
17
```
18
19
Usage example:
20
21
```python
22
from django.views.generic import CreateView
23
from braces.views import CsrfExemptMixin, JsonRequestResponseMixin
24
25
class APICreateView(CsrfExemptMixin, JsonRequestResponseMixin, CreateView):
26
model = MyModel
27
28
def post(self, request, *args, **kwargs):
29
# Process JSON data without CSRF token
30
data = self.request_json
31
# Create object...
32
return self.render_json_response({'status': 'created'})
33
```
34
35
**Note**: CsrfExemptMixin should be the leftmost mixin in inheritance chain.
36
37
### User Context Injection
38
39
Automatically pass the current user to form initialization.
40
41
```python { .api }
42
class UserFormKwargsMixin:
43
"""Automatically include request.user in form kwargs"""
44
45
def get_form_kwargs(self):
46
"""Update form kwargs with current user"""
47
```
48
49
Usage example:
50
51
```python
52
from django.views.generic import CreateView
53
from braces.views import UserFormKwargsMixin
54
55
class UserAwareCreateView(UserFormKwargsMixin, CreateView):
56
model = MyModel
57
form_class = MyModelForm
58
59
# Form will receive user in __init__
60
```
61
62
Form implementation:
63
64
```python
65
from django import forms
66
67
class MyModelForm(forms.ModelForm):
68
def __init__(self, *args, **kwargs):
69
self.user = kwargs.pop('user', None) # Extract user from kwargs
70
super().__init__(*args, **kwargs)
71
72
# Use self.user for field customization
73
if self.user and not self.user.is_staff:
74
del self.fields['admin_notes']
75
76
class Meta:
77
model = MyModel
78
fields = '__all__'
79
```
80
81
### Standalone Form Mixins
82
83
For direct use in form classes (imported from `braces.forms`):
84
85
```python { .api }
86
class UserKwargModelFormMixin:
87
"""Form mixin for popping user out of kwargs and attaching to instance"""
88
user = None
89
90
def __init__(self, *args, **kwargs):
91
"""Remove user from kwargs and assign to self.user"""
92
```
93
94
Usage example:
95
96
```python
97
from django import forms
98
from braces.forms import UserKwargModelFormMixin
99
100
class MyModelForm(UserKwargModelFormMixin, forms.ModelForm):
101
def __init__(self, *args, **kwargs):
102
super().__init__(*args, **kwargs) # Automatically extracts user
103
104
# Now self.user is available for customization
105
if self.user and not self.user.is_staff:
106
del self.fields['admin_notes']
107
108
class Meta:
109
model = MyModel
110
fields = '__all__'
111
112
# Usage in view
113
class MyCreateView(UserFormKwargsMixin, CreateView):
114
model = MyModel
115
form_class = MyModelForm # Form will receive user automatically
116
```
117
118
### Success URL Handling
119
120
Automatic success URL generation from named URL patterns.
121
122
```python { .api }
123
class SuccessURLRedirectListMixin:
124
"""Automatically reverse success_list_url as success_url"""
125
success_list_url = None
126
127
def get_success_url(self):
128
"""Return reversed success url"""
129
```
130
131
Usage example:
132
133
```python
134
from django.views.generic import CreateView
135
from braces.views import SuccessURLRedirectListMixin
136
137
class CreateItemView(SuccessURLRedirectListMixin, CreateView):
138
model = Item
139
success_list_url = 'item:list' # URL name to redirect to after success
140
```
141
142
### Form Validation Messages
143
144
Consistent success and error messaging for form processing.
145
146
```python { .api }
147
class MessageMixin:
148
"""Add messages attribute for Django's messages framework"""
149
# Provides self.messages with methods: add_message, debug, info, success, warning, error
150
151
def __init__(self, *args, **kwargs):
152
"""Initialize with class name reference"""
153
154
class FormValidMessageMixin(MessageMixin):
155
"""Set message when form passes validation"""
156
form_valid_message = None
157
158
def get_form_valid_message(self):
159
"""Validate that form_valid_message is set correctly"""
160
161
def form_valid(self, form):
162
"""Set form valid message for standard validation"""
163
164
def delete(self, *args, **kwargs):
165
"""Set form valid message for delete operations"""
166
167
class FormInvalidMessageMixin(MessageMixin):
168
"""Set message when form fails validation"""
169
form_invalid_message = None
170
171
def get_form_invalid_message(self):
172
"""Validate that form_invalid_message is set correctly"""
173
174
def form_invalid(self, form):
175
"""Set form invalid message for validation failures"""
176
177
class FormMessagesMixin(FormValidMessageMixin, FormInvalidMessageMixin):
178
"""Combines valid and invalid message mixins"""
179
```
180
181
Usage examples:
182
183
```python
184
from django.views.generic import CreateView, UpdateView
185
from braces.views import FormValidMessageMixin, FormInvalidMessageMixin, FormMessagesMixin
186
187
# Success messages only
188
class CreateWithSuccessView(FormValidMessageMixin, CreateView):
189
model = MyModel
190
form_valid_message = "Item created successfully!"
191
192
# Error messages only
193
class UpdateWithErrorView(FormInvalidMessageMixin, UpdateView):
194
model = MyModel
195
form_invalid_message = "Please correct the errors below."
196
197
# Both success and error messages
198
class FullMessageView(FormMessagesMixin, CreateView):
199
model = MyModel
200
form_valid_message = "Item created successfully!"
201
form_invalid_message = "Please fix the form errors."
202
```
203
204
### Advanced Message Usage
205
206
Direct access to Django's messages framework:
207
208
```python
209
from django.views.generic import FormView
210
from braces.views import MessageMixin
211
212
class CustomMessageView(MessageMixin, FormView):
213
def form_valid(self, form):
214
# Direct message usage
215
self.messages.success("Form submitted successfully!")
216
self.messages.info("Processing will begin shortly.")
217
218
# Conditional messaging
219
if form.cleaned_data.get('notify_admin'):
220
self.messages.warning("Admin will be notified.")
221
222
return super().form_valid(form)
223
224
def form_invalid(self, form):
225
self.messages.error("There were errors in your submission.")
226
227
# Add specific field errors
228
for field, errors in form.errors.items():
229
for error in errors:
230
self.messages.error(f"{field}: {error}")
231
232
return super().form_invalid(form)
233
```
234
235
## Common Usage Patterns
236
237
### Complete Form Processing Pipeline
238
239
Combine multiple mixins for comprehensive form handling:
240
241
```python
242
from django.views.generic import CreateView
243
from braces.views import (
244
LoginRequiredMixin, UserFormKwargsMixin,
245
FormMessagesMixin, SuccessURLRedirectListMixin
246
)
247
248
class CompleteCreateView(
249
LoginRequiredMixin,
250
UserFormKwargsMixin,
251
FormMessagesMixin,
252
SuccessURLRedirectListMixin,
253
CreateView
254
):
255
model = MyModel
256
form_class = MyModelForm
257
login_url = '/login/'
258
form_valid_message = "Item created successfully!"
259
form_invalid_message = "Please correct the errors below."
260
success_list_url = 'myapp:item_list'
261
```
262
263
### API Form Processing
264
265
Combine with JSON mixins for API endpoints:
266
267
```python
268
from django.views.generic import CreateView
269
from braces.views import CsrfExemptMixin, JsonRequestResponseMixin, UserFormKwargsMixin
270
271
class APIFormView(CsrfExemptMixin, JsonRequestResponseMixin, UserFormKwargsMixin, CreateView):
272
model = MyModel
273
form_class = MyModelForm
274
275
def form_valid(self, form):
276
# Save object
277
self.object = form.save()
278
279
# Return JSON response
280
return self.render_json_response({
281
'success': True,
282
'id': self.object.pk,
283
'message': 'Created successfully'
284
}, status=201)
285
286
def form_invalid(self, form):
287
# Return form errors as JSON
288
return self.render_json_response({
289
'success': False,
290
'errors': form.errors
291
}, status=400)
292
```
293
294
### Conditional Form Processing
295
296
Dynamic form behavior based on user or context:
297
298
```python
299
from django.views.generic import UpdateView
300
from braces.views import UserFormKwargsMixin, FormMessagesMixin
301
302
class ConditionalUpdateView(UserFormKwargsMixin, FormMessagesMixin, UpdateView):
303
model = MyModel
304
305
def get_form_valid_message(self):
306
if self.request.user.is_staff:
307
return "Administrative update completed."
308
return "Your changes have been saved."
309
310
def get_form_invalid_message(self):
311
return "Please correct the errors and try again."
312
313
def form_valid(self, form):
314
# Custom validation based on user
315
if not self.request.user.is_staff:
316
# Remove admin-only changes
317
form.instance.admin_approved = False
318
319
return super().form_valid(form)
320
```