Django templates inheritance between apps - django

In Django templates there is extends tag used like {% extends "base.html" %}.
I want if possible to name templates in several apps the same (like templates/bookkeeping/bookkeeping.html).
I want the more specialized app (which handles bookkeeping for a particular project) to extend a template in a less specialized app (which handles common tasks for bookkeeping for several our projects) with extends. Particularly in the less specialized app I create a template without much design. In the more specialized app I want to present the same information but with a particular design (CSS, etc.)
What can be done about this in Django 1.11?
If it is impossible to use extends of a template with the same template name (but different app), what are other possible ways to solve the problem? I could check existence of derived.html and fall back to base.html if there is no derived.html, but this would lead to writing tedious Python code. Is there a better way?

Could you not just name the directories for the templates in each of the apps as following:
app1/templates/app1/bookkeeping/bookkeeping.html
app2/templates/app2/bookkeeping/bookkeeping.html
Then in the more specialised app (app2) extend by using:
{% extends "app1/bookkeeping/bookkeeping.html" %}
Or am I missing something here?
Edit:
You could link your Python code to point to one template, say templates/pages/bookeeping_base.html. In that template you could say:
{% if project.is_specialised %}
{% include 'app2/bookkeeping/bookkeeping.html' %}
{% else %}
{% include 'app1/bookkeeping/bookkeeping.html' %}
{% endif %}
Then as I described above, the app2 template could still extend the app1 template.

Related

Django Combine two templated from different apps

I have two apps with the following structure
project->
main app->
templates->
dashboard.html
my app->
templates->
mydashboard.html
I want to include mydashboard into dashboard, well this is possible using include template tag. but my problem appears when I have to pass some parameters into mydashboard, let's say they are named param1 and param2 these parameters are the variables which I have to load from my app app. well one possible method is to filling these params in dashboardview in mainapp and pass them using include tag into mydashboard.html like below
def user_dashboard(request):
...-->here I have to get data from my app (this view is in main app and I do not want to make main app be dependent to my app
return render(request, 'dashboard.html', {'param1': 0, 'param2': 34})
then in dashboard.html I add this part
{% is_app_installed "myapp" as is_myapp_installed %}
{% if is_myapp_installed %}
{% include "myappdashboard.html" with param1=param1 param2=param2 %}
{% endif %}
It seems the above method works but the main problem is that using this method mainapp is dependent to myapp and I do not want to this happens.
is there any other method to load those param1 and param2 inside myapp?
thanks
I can't see the details of the templates, but if you want to decouple the two templates I suggest you to rethink how you organise your templates logic. Try to rearrange the logic adding a base_dashboard.html in a common template dir with snippets and base templates to share between the apps.
Then the myappdashboard.html and dashboard.html can extend it with {% extend base_dashboard.html %}.

base.html for Django Registration Redux

I am using django-registration-redux and everything works like a charm. However, I am a bit dissatisfied with the fact that it forces me to name the base template that it uses base.html, and that I have to put it in the templates directory.
I'd rather have it somewhere like this:
"/templates/registration/redux_base.html"
Is it possible to define this somewhere in my settings.py? I could not find that, but I think this must be possible. (Otherwise I am getting name clashes with other apps which is frustrating...)
Almost all templates from redux are extending template "registration/registration_base.html", except of templates for activation (for some reason they are extending directly from "base.html"). Template "registration/registration_base.html" looks literally like this:
{% extends "base.html" %}
So you can override that template (simply by creating "global" template for project on that location) and define here another {% extends %} or your whole new template.
But templates for email activation, as I mentioned above, are extending directly from "base.html" so if you are using them, you must overrite them separately.
Whenever it bothers you simply replace
{% extends "base.html" %}
with
{% extends "registration/redux_base.html" %}
And ofcourse create redux_base.html as you wish.

How can two apps respond to the same URL in Django?

I think I'm missing a basic concept here. In the stereotypical Django project, you'd have two apps responding to different urls:
http://localhost/myproj/app1/33
http://localhost/myproj/app2/newcomment.html
But what mechanisms exist to handle cases where the two apps are complementary - say one provides content, and the other provides presentation? Or maybe one is content and the other is a kind of static, side-wide content that should appear on every page.
In particular, I don't understand how both apps can use template inheritance to extend the same template. Imagine there's a base app "baseapp" with a template "base.html":
...
<div blah blah>
{% block content %}
{% endblock %}
...
App1 extends it:
{% extends "baseapp/templates/base.html" %}
{% block content %}
... here's the actual content...
{% endblock %}
App2 adds a little banner or something:
{% extends "baseapp/templates/base.html" %}
{% block content %}
<div class="banner">Please support our site!</div>
{{ block.super }}
{% endblock %}
So what are the ways that both templates can get displayed? I can think of:
app1 could extend app2's templates. But this seems wrong: app1 is the content provider, and shouldn't be dependent on something as trivial as app2.
app2 could extend app1's templates. But this seems wrong: now the URL scheme would have to funnel every URL through app2 (if I understand correctly)
middleware?
As I said, I'm probably missing something very basic. Or I'm making some very faulty assumptions that I don't know about. (This question is my third attempt, after Embed an optional Django application in another page, if that app is present and How to capture and display information external to my webapp, but relevant to users of it? - I'm having trouble framing the issue.)
App doesn't respond to an URL, a view does. View is a function that can use models, forms and other object from any app. There isn't any problem here.
If you want to add something to template, inheritance isn't the only way. You'd better use custom context processor or custom template tag.
I think what I was actually missing here:
Apps can override templates just by including a template of the right name in the right subdirectory. The Django docs don't make this very clear, that I can see: they refer to this functionality in the context of Admin templates
When overriding a template as above, you can't extend it, but:
This snippet lets you both override a template and extend it: http://djangosnippets.org/snippets/1376/
Here's a closely related question: Django: Overriding AND extending an app template

django extends different base templates

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?

django: how to interconnect various logical pieces of a webpage

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