Render a block through a template that will be added to an existing page as well as it's own - django

I have a page which is for album/picture management with 2 sections: Albums and Pictures.
When an album is selected the pictures block needs to change via AJAX to reflect the album selected.
This means the rendered pictures block needs to be provided to the Albums page as well as be available as it's own View for the AJAX source.
I understand I could solve this by making the pictures block always render from AJAX even when the album page loads, however I would like to deliver the default album pictures within the initial page load if possible. In order to do that, I'd like to render the pictures block via the same template in the Album page view as is used for the Picture AJAX View.
I'm only familiar with providing templates as a template_name property within an TemplateView object.
I guess I could simply call an instance of PictureView using inclusion_tag, and pull the data I need out of the render_to_response (I haven't tried this yet, I'm just theorizing) however that seems a bit dirty to me. I'm wondering if there's a more elegant solution to this problem?
Thanks!

jQuery, Django templates, JS templating and backbone.js should tie this together.
I would suggest having a dedicated template for the Pages block. Include this template in the Django template for your page.
For dynamic updates use a JS templating library such as included in underscore.js or moustache.js. You can change the template demlimiters used so that they are the same as djangos.
Include the raw Pages block template into a javascript template block - use the django ssi tag.
Use django-tastypie to set up an api that returns the data for Photos as JSON. Your template library can then use data to fill in the template in the JS template block and you can then replace the Photo block with this rendered HTML. Use of backbone.js should ease the tying of DOM elements and JS events.

If I understand your question correctly, I did something similar once with the subsection having its own template file, which only describes that one section of the page. I used the include tag to include it into the page template, so it loaded when the page did and then rendered that template with updated values and replaced it on the page with AJAX when the content was meant to change.
Is that an option for you?

Related

Zurb foundation Interchange with Django templates?

Is Zurb Foundation's Interchange compatible for use with Django templates? I can't see a way to get them to work together, though the issue is just a technical one - Interchange seems to want html file paths, while Django's html templates render inline.
I suppose it would be possible to render the necessary templates each request into temporary files and hand those to Interchange, but that's not a very clean solution and would require a lot of boilerplate. I'm looking for a cleaner solution or for an alternative within Foundation and Django.
No, Foundation's interchange is javascript that runs in the browser within the HTML file produced by Django on your back-end. It's meant to be used for loading static files, mostly media, dependent on the size class of your browser view. E.g. inside and <img> tag:
<img data-interchange="[{% static 'images/my_background_small.png' %}, small], [{% static 'images/my_background.png' %}, medium]>
If you want to serve different HTML to different types of end-devices, you have to add that logic to your Django app's view, so that it uses a different template depending on the client. In general there are a few approaches:
What people do nowadays: Write responsive templates so that the same
HTML is served for mobile and desktop. For the few minor
differences, you can hide/show divs depending on the media class.
Check the device in your middleware and pass it as parameter to your views and templates so you can make decisions on it. Check django-mobile for example
Check the device in your server (apache or nginx) and add an HTTP header to your request that you can parse in your view (e.g. request.META.get('HTTP_MOBILE_SITE','no'). Example here

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 :)

Difference between template include and jquery.load?

Is there a difference in how django treats a 'loaded' page/template if i use the django-template specific include-tag, or jQuerys load-function?
If you use Django's {% include %} tag, the template is constructed by the server and displayed in the browser after the construction is complete. On the other side, if you use jQuery.load(), the requested template is included on the client-side using an AJAX request after the base template has finished loading.
In both cases, the displayed result in the browser should be the same. The advantage of jQuery's method is that you can load the template later on, for example when you click a button on the page, without the need to reload the entire page in the browser. So you can handle user interaction in a more interactive way. An advantage of server-side method is that the entire DOM and content resides in the HTML file and can therefore be indexed by search engines if that should matter to you. HTML included by client-side JavaScript is not visible for search engines.
Generally speaking, if you just want to include HTML once a requested webpage gets loaded, use the server-side method using the include tag. It's more user-friendly and efficient to let the server do the template handling, especially if the templates are very large.
The ssi or include tags are included on server side (in this case by django). jQuery includes client based.

Sidebar with django, layout or view?

I want to make a sidebar for my webapplication. It contains the following content:
A search bar
a list of tags
links to recent posts (with year and month)
I want to include this sidebar in every site/view. So my first guess is that it would belong to a layout.
But it's also dynamic and as far as i know layouts are static.
How do I avoid redundancy in my views/layouts and still have the sidebar on every site?
To have context data passed to multiple templates you have different options in django; You could either:
Make a Template Tag which can pull in the relevant data and render it and reuse it in every template you need to (or just insert it in a base template and use template inheritance).
Use a context processor: It will be called with every request and add data to every view's context that uses RequestContext.
Using Django's class based views you could have all your views inherit from a base view which adds data to your context.
If you need data from your database I would rather go with using a template tag than using a context processor as it will be called for every view.
For static content in your sidebar (e.g. search form), its straight forward template/html.
For the dynamic content like list of tags, recent posts:
Once in the template you have identified a elements (div or something else) to put this info, you can populate its content using either your custom template tag or having custom context processor.
In your case, if the content doesn't really depend upon request parameter or url, template tag would be better choice.
Reference Custom template tag Custom Context Processor

How can I put a block of dynamically generated content into a django template?

I want to include things like twitter status, or delicious tags, in my django templates.
These things are dynamic, yet regular. How would this be done?
There are a number of ways to handle this, so you can choose a method that best matches your own personal style or requirements:
Template context variable: as answered by Alex you can put your content into a context variable that is included in the context of every template created by every view. Django even provides a mechanism for doing this automatically, called a context processor. Pros: very straightforward. Cons: won't dynamically refresh new content on client browsers.
AJAX dynamic loading: as mentioned by Alex and Dave you can dynamically load your content using AJAX methods. As an example using jQuery, you would put a placeholder in your template something like <div id="twitterfeed"></div> and then in a javascript block in your template put $("#twitterfeed").load("{% url twitterfeed %}"); where twitterfeed is a url so named in your urls.py. Pros: will dynamically update browsers. Cons: can be tricky if you don't know Javascript.
Inclusion tag: Django provides a type of template tag called an inclusion tag, which is basically a custom template tag that can render dynamic content. In a way it's similar to a context variable, except your code to generate the content will only be called when you use the custom template tag in your template instead of being called for every view. Another benefit is the content is generated from a template of its own. You could do this with a normal context variable of course, but it's not as clean (IMHO) as using an inclusion tag. Pros: very straightforward, clean. Cons: won't dynamically refresh new content on client browsers.
The simplest approach is to use {{ mycontent }} in your template (where you want the dynamically generated content to appear) and put the correspondence between mycontent and its value in the context you use to render the template -- i.e., the most fundamental part of django's templating.
If what you mean is that you want Ajax support whereby Javascript on the page continuously refreshes such content according to what the server wants it to be at any given time, I suggest looking into dojango, the Dojo/Django integration project -- it's not yet as fully mature as each of Dojo and Django are on their own (not version 0.4 yet), but it is already usable and useful.
A common technique is to leave a placeholder div in the generated content, then fill the div in on the client side via an AJAX call from Javascript that you include in the page.
That gives you the benefit of having a cacheable (fast loading) primary page, with separate dynamic bits. Depending on how live you want the dynamic bits, you can can even cache them for shorter durations.