# as a context_processor from .forms import SomeLoginForm def loginFormProcessor(request): ctx = {} if not request.user.is_authenticated(): ctx['login_form'] = SomeLoginForm return ctx # your template {% if not request.user.is_authenticated %} {% crispy login_form %} {% endif %}
I was using this pattern for a rather complicated form without thinking about the overhead incurred. However, when new-relic revealed this was taking ~600 ms per render, I knew it had to be fixed.
The simplest solution is template caching, making our template look like so:
# your template {% load cache %} {% if not request.user.is_authenticated %} {% cache 99999 login_form_cache %} {% crispy login_form %} {% endcache %} {% endif %}
The problem with this is we still incur the overhead in our context processor. We can avoid this by doing all our work within the cache tag. First, we need to move the logic of generating the form out of the context processor and into a template_tag.
# our template_tag.py file @register.assignment_tag def get_login_forms(): from ..forms import StepOne, StepTwo, StepThree ctx = {} ctx['first'] = StepOne ctx['second'] = StepTwo ctx['third'] = StepThree return Context(ctx)
Now, we need to integrate this tag into our text, so our final template looks like the following (this is also more related to my particular example where I have a multi-stepped form):
# our template file {% load cache our_tags %} {% if not request.user.is_authenticated %} {% cache 99999 login_form_cache %} {% get_login_forms as modal_login_forms %} {% crispy modal_login_forms.first %} {% crispy modal_login_forms.second %} {% crispy modal_login_forms.third %} {% endcache %} {% endif %}
This alone made the server response time come from ~2-3 seconds down to 0.69 seconds. Not too shabby.
Note: This code should run but I didn't test it as it isn't exactly my code copy & pasted, but an example.
Why are you not getting your form from the view? And just render it (with cache if you want)? Plus the django cripsy forms can be very heavy for rendering big forms / complex design output etc.
ReplyDeleteHi Florian,
DeleteI took this approach because the form is rendered across many views, there is no single view to get the form from. For inclusion in views, the only approach I could think of would be to create a mixin, and include that class across all relevant views (if you were considering an alternative that's cleaner, it'd be useful to know). That would require me knowing all the views it should go into, whereas just including it in the correct base template automatically ensures it goes everywhere it should go. It just seemed cleaner this way.
Chris