- March 29, 2015
- django mixin cbv
- 0 (after 0 ratings)
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.
process_preview - function executed after submitting the form for the first time (default is to do nothing)
done - function for the action if the confirm page is sent (defaults to whatever form_valid of the django cbv does)
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()