I understand we can use "extends variable" in the template to switch between two different extended templates.
e.g.
views:
if something:
base = 'base1.html'
else:
base = 'base2.html'
return render_to_response ('template.html', {'base':base})
template.html:
{% extends base %}
Normally that works fine. However, my problem is that I am using django-registration of which I don't have to write my own view to handle the registration and login process. That also means that I am not able to pass the variable to the template. Though I do have the registration templates under my project directory. (like login.html)
Unfortunately, Django can't do this in the template:
{% if something %}
{% extends 'base1.html' %}
{% else %}
{% extends 'base2.html' %}
{% endif %}
The only way I know that the 'variable base' can be passed down to the auth-login is to write my own views like login, logout,etc. This seems like not fitting the DRY model and fairly error prone going forward.
Is there another way that I can accomplish this? Or any pointers to workaround the problem?
Thanks.
-P
If it's just 2 (or 3) options where that 'something' can be made to a Boolean, then you could use the yesno filter:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#yesno
So:
{% extends something|yesno:"base1.html,base2.html" %}
If you want something a bit more free-form, then you could make use of the extra context / custom context processor option mentioned above, and try something like:
{% extends selected_template|default:"base2.html" %}
where selected template is just the path to whatever base template you like.
To be honest this looks to me like a code smell - I've used django-registration a few times, I work on quite large sites and I never needed to extend a template from another template which is only known at run time.
Anyway, if you really want to pass a custom variable to a template rendered by 3rd party module, and you don't want to hack that module, then you have to use e.g. custom template context processor. Also, django-registration allows extra_context to be passed to its views, maybe that would be enough. You can also try monkey-patching. Or maybe you can try manipulating template folders or template loaders to get what you need.
But all these things are IMHO hacks and you shouldn't use different templates for one view, unless it's a generic view.
I think you should not place differences between the templates into the selection of different base templates. Having different base templates is what violates the DRY principle. Place the common things into a template, ie. registration.html, the differences into other templates that you call via 'include':
{%extends base.html%}
{%if something%}
{%include "type1.html"%}
{%else%}
{%include "type2.hmtl"%}
where the template names are the same as you would use in the view definition.
This probably isn't what you are looking for, but could you just include your conditionals in your base.html?
Related
I want to achieve something like this within a Django template.
{{ variable.function(parameter) }}
Where variable is a variable passed through a context to a template, in this case, an instance of a model.
I have tried different methods, but no one seems to work.
This is not possible in Django templates: they are crippled on purpose in order to prevent template designers from shooting themselves in the foot. The reasoning is that the only logic in templates should be presentation logic and all business logic should be kept in the view. Some people thinks it is fair enough and some think it is a bit condescending (those dumb template designers are not smart enough to use functions and methods safely).
I can think of 3 choices:
use jinja2 instead.
write a custom template filter.
keep all the logic in the view where Django designers think you are supposed to keep it.
I will not explain how to use Jinja2 because it is already explained in the docs and because the example in the question works verbatim if you switch to it instead of native Django templates. This simply works in Jinja2:
{{ variable.function(parameter) }}
Now the template filter solution: first you must follow a code layout convention. The filter itself would be something like this:
# at your_tag_library.py
#register.filter(name='call_with')
def apply_callable(callable, arg):
return callable(arg)
Then in the template you can do:
{% load your_tag_library %}
{{ variable.function|call_with:parameter }}
Of course the last option is the one from Daniel's answer - precompute the value in the view and just display the result in the template:
context['result'] = variable.function(parameter)
And in your template you just need {{ result }}.
There is no way to do this.
You can create another variable and pass it through the context so you could use it.
Like:
context['result'] = variable.function(parameter)
In your view.
And in your template:
{{ result }}
Is there a way to do isinstance/issubclass in a Django template? I realise I can write my own templatetag, but I'm surprised this isn't possibly which makes me think I'm either doing something wrong or missing something obvious.
I wish to display two different segments of markup, depending on which type of item I'm displaying whilst iterative over my collection. Thanks!
I think a simple template filter here fits the best. It is really quick to implement and easy to call. Something like this:
in templatetags/my_filters.py:
from django import template
from django.utils.importlib import import_module
register = template.Library()
#register.filter
def isinst(value, class_str):
split = class_str.split('.')
return isinstance(value, getattr(import_module('.'.join(split[:-1])), split[-1]))
in your template:
{% load my_filters %}
...
{% if myvar|isinst:"mymodule.MyClass" %}
...do your stuff
{% endif %}
Although the above is a sample code (not tested), I believe it should work.
For more information on custom template filters please see the django documentation
EDIT: Edited the answer to show that the filter argument is actually a string and not a python Class
If all of these inherit from a common base type, but you need to know which type it is, you may want to just implement a method on the base that returns the type - then you can call if foo.get_type == 'type1' (or whatever) in your template.
You are missing something here: the only logic in the template is supposed to handle template rendering. isinstance / issubclass clearly smell like view logic, and should be in the view. If the template rendering depends on those functions (which I guess it does), you should implement the logic in the view, and just pass the template what it needs to know:
# in the view:
if isinstance(some_obj, SomeClass):
do_fancy_template_stuff = True
else:
do_fancy_template_stuff = False
# in the template:
{% if do_fancy_template_stuff %}
<fancy_template_stuff />
{% endif %}
Remember: the django templating engine was created having non-programmers, like designers, in mind.
I would like to create separate templates for each part of the page like Navigation, Side bar, Login panel, etc. Django seems to use inheritance rather than composition. I was wondering if there is any support for separating templates out into parts and passing in template specific models to each template. I'm thinking of something like:
values = {
'navbar_data' = ...
'sidebar_data' = ...
}
{{ template.render('navbar', navbar_data) }}
{{ template.render('sidebar', sidebar_data) }}
There are many good ways to do this.
You can use the builtin templatetage include for this. This template tag allows you to to use and reuse specific fragments of a template. This is usually most useful for mini templates that say represent a single model and will be used throughout the site. This can be especially useful if you combine it with the with templatetag to allow you to craft the context used in the included template
Alternatively just simply using block may give you the feel you're looking for
Finally you can use custom inclusion templatetags (https://docs.djangoproject.com/en/1.4/howto/custom-template-tags/#inclusion-tags) to give you an even deeper level of control. These will allow you to render a subtemplate with a completely custom context.
That is what templatetags are for. You define a tag in a file called myapp/templatetags/mytags.py, then in your template do this
{% load mytags %}
{% navbar %} {% sidebar %}
The official documentation has plenty of information about this.
I was thinking about putting my static pages in the database (simple model of url, title and content) and then having a basic base_static.html template - making them super easy to edit (from admin interface) if necessary.
I know you can easily escape html like so:
{{ content|safe }}
or
{% autoescape off %}
{{ content }}
{% endautoescape %}
But I need to be able to use some of the template language in the static pages, e.g. a simple for loop to go over variables passed to it from the view.
Is this possible, or would you recommend simply using templates to serve the static pages?(They won't change that much ever)
Thank you for your help.
If you want to store templates in db (and that is what you want if you want to use a template language) you can use this app : django-dbtemplates.
Check this question: Extending Django Flatpages to accept template tags
You may get some ideas from the solution exposed there
everyone. I'm just starting with django, so sorry for a possibly stupid question.
Imagine, I have a webpage with 3 logical pieces: content, dynamic menu, banners. It seems ok to me to have a template with something like:
{% include "banners.html" %}
{% include "menu.html" %}
{% include "content.html" %}
But then, how do I do it? Every piece has its separate logic in a separate view in its' separate app. How do I trigger execution of all three views and render all three templates?
P.S. Is there a sourceforge-like site for django apps where I could take a look at how people are doing stuff in real projects?
The standard way to do it is something as follows:
Templates:
Have a base.html that has the banners, menu and a body block which is empty.
For each template, extend the base.html and override the body block.
{% extends "base.html" %}
{% block body %}
-- Your this page's content goes here.
{% endblock %}
You can use the includes, where necessary, but prefer the extends where possible. Include was debated to be included in the template language.
Populating Context:
You now have a lot of templates with placeholders that need to be replaced with the real "context" values.
Pass the RequestContext, that should contain many standard requirements for the template.
For the values that you need in every template, write a template context processor.
Those context's that you need in this template, you populate in the view.
Using multiple app's views:
Most apps written for reuse will include template_name as a standard parameter, along with extra_context. You will need to call those views with these parameters.
Some apps go out of their way, to create a lazily evaluated response (like TemplateResponse) so that you can grab the context they populate, in your view.
Django reusable apps:
Are you kidding me? They are all over the Internet!
http://github.com/search?q=django&type=Everything
http://bitbucket.org/repo/all/?name=django
http://code.google.com/hosting/search?q=django&projectsearch=Search+projects