PreviewMixin adds a preview page for Django's CBV (FormView, UpdateView, CreateView). After a form has been submitted, it is returned again, optionally in a different template to confirm. If the form is submitted with the same data, the default "form_valid" function is executed.
Features:
1. process_preview
- function executed after submitting the form for the first time (default is to do nothing)
2. done
- function for the action if the confirm page is sent (defaults to whatever form_valid of the django cbv does)
3. preview_template_name
- variable with the name of the template for the confirm page (defaults to taking the same template as for the initial form)
4. new function security_hash
to calculate a hash which is added to the confirmation form.
Works kind of like django-formtools, just as a Mixin for the default Django cbv.
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 | from django import forms
from formtools.utils import form_hmac
import copy
class PreviewMixin(object):
'''
Mixin for a 2-stage form
For usage with the default django class-based views (CreateView, UpdateView, FormView)
Procedure:
First display a form in a template.
When submitted, execute process_preview, then redisplay the form.
If submitted again and the data matches the previous submit, run done.
Else run process_preview again and redisplay the form once again.
'''
stage = 1
preview_template_name = None
def get_template_names(self):
'''
Depending on the stage, return the appropriate template
Use the default template of the Django View for the first stage
If a different template is wanted for the second stage, preview_template_name can be set.
Otherwise the default template of the Django View is also used for the second stage.
'''
if self.stage == 2 and self.preview_template_name is not None:
return [self.preview_template_name]
return super(PreviewMixin, self).get_template_names()
def get_form(self, form_class=None):
'''
Add a hash value to each form.
If stage==1 (first form or previous invalid data), pass 0 as hash value
'''
form = super(PreviewMixin, self).get_form(form_class)
if self.stage == 2:
form.fields['hash'] = forms.CharField(initial='0', widget=forms.HiddenInput)
return form
def form_valid(self, form):
'''
Check if form was submitted the first or second time.
If it is the second time and the hash-value matches, run done()
Else run process_preview and return the second form.
Should not be overwritten.
'''
if self.security_hash(form) == self.request.POST.get('hash', '0'):
return self.done(form)
self.process_preview(form)
self.stage = 2
self.request.POST['hash'] = self.security_hash(form)
form = self.get_form(self.get_form_class())
return self.render_to_response(self.get_context_data(form=form))
def security_hash(self, form):
'''
Function to return the hash value of the form
'''
hash_form = copy.copy(form)
hash_form.fields.pop('hash', '')
return form_hmac(hash_form)
def process_preview(self, form):
'''
Function which is run after the form was valid for the first time.
Does nothing by default.
'''
pass
def done(self, form):
'''
Function which is run after the form was submitted the second time if it is valid and the hash values match.
By default does the same as the corresponding form_valid function of the class-based view it inherits from.
'''
return super(PreviewMixin, self).form_valid()
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 4 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.