Subrequests in Django templates - django

I'm working on my first Django project and have my templates setup with a base that all the others extend. In that base I want to have some user-specific navigation which means loading some values from the database to build the contents of a drop down menu. However I don't want to have to do this inside each view. Coming from Symfony2/Twig I would normally do this using a sub-request where I tell the template to render a view and that will use it's own template. Using syntax like:
{% render 'Bundle:Controller:action' with {} %}
How would I accomplish this same thing with Django? I've read over the docs a couple of times but can't find any way to do this.

You have two approaches:
(better)
- add the code to base.html (the one you're always extending) and only override it when you need to.
or
(worse)
- in every template use {% include %} to include your menus.html template.
Update: re-reading your question: you could modify the request in context-processor so your base.html would then have this information.

Custom template tags are what you want.

Related

How to add an html block across all pages (templates)?

I have a flask-admin app with quite a number of custom templates. I want to add an html block at the top of every page in the app. The obvious solution would be to add it to every template (and don't forget to add it to any new custom templates) but I hope there might be a better solution, to specify the html I want in a single place and have all future new templates automatically have it.
To simply insert HTML snippets into your templates you could use
{% include 'template_file.html' %}
To automatically get all new templates to use the HTML block try the jinja2 template inheritance which all of your templates would need to inherit from. Docs

django cms [aldryn newsblog] replace template for plugin

I need to replace same plugin template on different subpages - e.g. on frontpage I need specific slider template for latest articles, in detail article I need small list, on search result without images etc.
[note: everything about aldryn newsblog app - I don't mean my own plugin!]
*(something like custom template per plugin instance)
How to replace it ? Extending template is not quite what I need - inheritance is from bottom - from lower subtemplate to base.html - but that plugin have hardcoded lower template.
Tons of IF block in template is irrational then we think in MVC.
*( like here Render Django-CMS plugins differently on different splaceholders/templates )
Or maybe just write custom template with using hardcoded including plugins ? But using django cms placeholder editor is very useful and it'll be better to keep working in that way :///
So, I create front.html base template for frontpage,
put some plugins to placeholders - and need to replace subtemplates for this plugins only in this front.html and keep subtemplates for that plugin in other places - this is main goal.
It will be the best, when django cms / aldryn newsblog provide option "custom template" per plugin instance :|
( like this one http://www.ilian.io/django-cms-plugins-with-selectable-template/ )
If I understand your question correctly (it's late here), you need a way to override plugin templates on a plugin instance basis because hacking django templates is not the way to go (I agree).
Django CMS does allow you to override plugin templates on an instance basis.
As shown in http://docs.django-cms.org/en/develop/how_to/custom_plugins.html?highlight=get_render_template#the-simplest-plugin
In your CMSPluginBase subclass add the following:
def get_render_template(self, context, instance, placeholder):
# criteria goes here
return 'sometemplate.html'
As far as how to know which template to render when (criteria), you can do a few things.
Use the page's reverse id:
page = instance.page
templates = {
'homepage': 'plugin_home.html',
'about': 'plugin_about.html',
'contact': 'plugin_contact.html',
}
return templates[plugin.page.reverse_id]
This approach has a few drawbacks:
Relies on plugin being bound to a page. (plugins can live outside of pages)
Can only work with pages that have reverse id set and reverse ids
are unique per page which means you would have to list reverse id
for every page you want to change template for.
Use a page extension to set a category per page:
Checkout http://docs.django-cms.org/en/develop/how_to/extending_page_title.html
With this approach you can then set some sort of category to multiple pages and so you can target multiple pages in one shot like so:
page = instance.page
extension = get_page_extension(page) # Check out docs for this
templates = {
'category_1': 'plugin_category_1.html',
'category_2': 'plugin_category_2.html',
'category_3': 'plugin_category_3.html',
}
return templates[extension.category.name]
Pros:
Can target multiple pages in one shot
Cons:
Relies on plugin being bound to a page.
A bit more complex
Use a template context variable:
In your templates, depending on how you're rendering your plugins, you can
provide a context variable like so:
{% with category='category_1' %}
{% placeholder 'content' %}
{% endwith %}
or
{% with category='category_1' %}
{% render_plugin yourplugin %}
{% endwith %}
Then in your get_render_template method you can access this context variable and do the following:
# Use .get() to provide fallback
category = context['category']
templates = {
'category_1': 'plugin_category_1.html',
'category_2': 'plugin_category_2.html',
'category_3': 'plugin_category_3.html',
}
return templates[category]
Pros:
No extra models.
Can target multiple pages in one shot.
Cons:
The only one I can think of is these random {% with %} in
templates.
I completely missed the newblog part, so in order to override the newsblog plugins or any plugin, just subclass the plugin class you want to override and unregister the original and then register yours, make sure yours has the same class name.
Maybe you can make the whole template logic above into a mixin to use throughout your project.
I've always wanted to give Zinnia a look, but I'm too far into working with NewsBlog on a site right now to do it (and blogs have already been posted and whatnot). You can always just add a few extra placeholders in the template (it's not the most efficient looking thing ever, but it's no load on the framework if you add a placeholder and leave it blank), that way they aren't static, and then you can put whatever plugins you want to inside of them. You can customize each component in NewsBlog pretty easily by just adding whatever you want in the structure mode. Things get trickier when it comes to having multiple blogs that act differently, but even then, as long as you're not adding components into the static placeholders provided by NewsBlog (or as I so elegantly learned it, "don't put the stuff in the blocky-things with the pins next to them), you can create different namespace for the different blogs (either in the admin, under "Configs" in the NewsBlog section, or when creating a new page and hooking it to the NewsBlog app), and you can have different templates on different blogs.
EDIT: This is a really excellent resource for touching up NewBlog without throwing the baby out with the bathwater (after three months of learning DjangoCMS, I'm still finding myself referencing it for fine-tuning pieces of NewsBlog, and to refresh my grasp on templatetags and other things that are overwhelming and have quickly left my brain along the way): https://www.django-cms.org/en/blog/2016/02/16/build-a-website-without-knowing-python-django-part-two/
*I linked to part two, as the first part deals with how to initially setup a project, and I assumed it probably wasn't relevant. Then again, if you're using Aldryn, there are some useful bits in there that can extrapolate if you're having trouble with customizing the boilerplate (or other things you'd like to configure that an Aldryn setup handles for you -- which is super awesome most of the times, but when it's not super awesome, it's usually super frustrating :)

Reusable templates for common display elements (tables, etc.) in django

I'm building a django application that has similar-looking display elements on several different pages.
For example, the projects.html page has a table that lists projects and some related information; the documents.html page has a similar-looking table
It seems like there ought to be a way to define a "my_kind_of_table" template and then insert it into different pages as necessary:
{% proj_list | create_my_kind_of_table:name,description,last_update %}
and then...
{% doc_list | create_my_kind_of_table:name,header,owner %}
I suspect that django can already do this, but I don't know what to search for. Any suggestions?
How about {% include ... %}?
To add context variables that all tables needs, then you have three solutions to pick: One is what I would call the "old fashioned" way, and is to have special function that is called by all views that needs to add context function. The second is to create a function decorator, that is used on the function that returns the response. The third way can be used if you use the new 1.3 class-based views, then you can create a mixin-class that your view-class inherits, and that adds these things in its own get method.
Custom template tags and filters will accomplish this: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/

How to call controller function from template in Django?

How to call controller function from template in Django instead of hardcoding URIs?
I guess You mean "link to it".
This can be done via {% url %} tag, see docs
If Your intent is to call view function directly, this is not possible by design - templates should not know about views, it's a separate layer.
How to call controller function from template
Not sure what you mean here. If you mean to provide an an HTML link to it see the second part of my answer below.
instead of hardcoding URIs?
In case you haven't already, use the {% url %} tag. Use this in conjunction with named URLs in your url config.
If you mean adding URL to the resulting HTML, then either use {% url %} tag as others, or get used to writing and using model_instance.get_absolute_url(). Personally I'm using the latter whenever possible, adding also custom "URL functions" like get_delete_url() etc.

django query db on every request

i have a navigation element that is determined by values in a database.
no matter what view it is, i need to get these navigation objects out of the database.
where in the code can i tell it to set a template variable containing all the navigation objeccts without setting it in every view?
It sounds like a good use for a context processor.
Right way to do this is to use templatetag. Then you don't have to include it in every view, just in your templates like {% load navigation %} {% navigation %}
How to write one:
django docs on template tags (read overview and inclusion tags)
anoher resource