Django Client Side Filtering - javascript

I'm pretty new to Django and I'm working on a site where I want the user to be able to filter out objects based on the objects' timestamp. I could easily do the filtering in views.py and reload the template, but how should I do this filtering client side?
Would it be a good idea to just load everything:
{% for obj in all_objects %}
<p>{{obj.time}}</p>
{% endfor %}
and then use javascript to hide and show the relevant objects? I don't expect more than 1,000 objects.
I've taken a look at this:
http://dustindavis.me/dynamic-filtered-drop-down-choice-fields-with-django.html
and the author says that he would use AngularJS instead of a custom AJAX solution.
Is Angular my best choice or are there other frameworks that are easier to integrate with Django?

You don't need a whole framework such as Angular to filter your results, though I'd certainly recommend using one of the popular MVC frameworks.
However, if you go that route you will significantly change the architecture of your django application since Angular and such are really built for single-page applications, and would suit you best if your django project was exposing an API rather than rendering HTML.
Having said that, to solve your problem, I would continue to use the same django template, and load the content of the list into a hidden HTML element.
Then in your page's Javascript code, you can extract the relevant items from the list based on user selections. That code would be entirely Javascript, though.
As a tip, i would use the django template to insert the filtering parameters as data attributes of your hidden HTML tags. An example:
{% for obj in all_objects %}
<p data-time='{{obj.time}}' data-somefilter='{{obj.somefiter}}'>{{obj.time}}</p>
{% endfor %}
This way you can easily use Jquery selectors to filter the data based on the requirements and then copy over the results to the visible HTML section where you display the filtered list

Related

Django - change Dictsort using a Javascript onclick listener?

Is it possible to change what dictsort is sorting by using Javascript?
Here is my sort code:
{% for product in products|dictsortreversed:'price' %}
....stuff happening here
{% endfor %}
What I want is for when a user clicks on a sort option for the dictsortreversed:'price' to become dictsort:'price'.
Is this possible at all? Or should I try and find a different way to do this?
This is not possible in a direct way, because dictsort and dictsortreversed are template filters that Django applies at rendering time in the server, and Javascript is executed in the client browser after rendering an cannot influence rendering inside the server.
Proven methods you could use:
Make a new HTTP request when the user selects a sort option and pass this sort option as a HTTP GET parameter (query string parameter), and modify your Django view to sort the data according to that param (maybe by calling order_by on the QuerySet).
Conditional sorting is better done at the view level, not in your templates.
Use dynamic sorting through Javascript, maybe by employing tested tools like datatables or similar ones (Google will gladly help you with that).
See also other questions about sorting with Javascript.

Avoiding ng-include while allowing flexibility in rendering sub-templates

I have a component which is treated like a "blog post" for example. A single piece of content that contains data. I've created a bunch of templates that can be rendered using ng-include in my "blog" template.
A few examples:
Blog content (title, author, etc.)
Related Posts
Author information
Email signup
(Any infinite number of possibilities)
I can't hardcode these into the template for a few reasons.
Each section needs to be able to be presented in any order (order dependent upon JSON)
All of these options need to be optional
Normally I would use some kind of foreach loop in the angular template and conditionally load each template via ng-include, but I've read this could have a major performance hit.
What's the best way to approach this using Angular 1.6.4 and components?
What about using a function to decide which template to include? This is a very generic example.
<div ng-include="vm.getTemplate(myVar)">
</div>
function
vm.getTemplate = function(myVar) {
//logic to decide template
return '../templates/someTemplate.html';
}

How to format different templates for angular 2 blog posts?

I want to create a blog with angular 2. I am struggling to find the answer to my question.
My problem is I want each blog post template to be different because I'll have a different format for each post with different images, snippets and blocks of text so reading from a JSON object won't be sufficient.
For example if I was just creating a normal static website I would just create each blog post with its own custom HTML page and have the flexibility to format the page in any way.
But in angular to I need to stick with the one template, how can I have a different template for each post without creating a new component for each new post?
Advice needed, thanks.
Use innerHTML to display field as HTML. Assuming you have a BlogPostComponent and a property content which is HTML. Then in your template, you can do something like this:
<h1>{{ title }}</h1>
<div [innerHTML]="content"></div>

Extending Handlebars.js templates

Is there a way to extend templates like in Django? My base template has a header that only needs to be a few pages. I'd like to change that for the the other templates.
Something similar to
{% extends "base.html" %}
...
{% endblock %}
I'm using Ember.js.
As far as i know this notation does not exist, also i haven't seen the concept of inheritance on handlebars templates layer.
However, i can think of two ways to achieve what you want,
1. using the {{partial}} helper http://emberjs.com/guides/templates/rendering-with-helpers/
The {{partial}} helper can render the header part and it can be included only on those templates of the pages that require the header.
2. using layouts http://emberjs.com/guides/views/adding-layouts-to-views/
Have two layouts one with the header and another without it, then specify on the pages/views that need the header the corresponding layout using the layoutName property.
I was looking for the same as I come from the same Django background. Here I've found exactly what you are looking for. It uses another module from npm called Handlebar-layouts. which is really useful.

When using (only) a templating system, how should I manage CSS, javascript etc for sub-templates?

I've had this same question when working with different templating systems in different languages in the past, so first,
The general question
I want to use a sub-template to include a certain UI component which might appear in different places on a number of different pages. This UI component requires certain CSS and JS files.
I want to Do The Right Thing with CSS and JS resources, which, as far as I know and in broad terms, is to a) combine as many as possible b) minify as much as possible and maybe c) put what I can at the end of my markup so the browser doesn't have to wait for them to load before displaying content.
So, if I've got various different UI components, as well as different headers and sidebars in different sections of the site, which all require their own special CSS and JS to function correctly, what's the best way for me to manage them through a templating system so that the final markup is as small and well-organised as possible?
Specifics of my situation
I'm working on a large legacy PHP site, on which, to give the original authors the benefit of the doubt, development may have begun before MVC became really mainstream, and before there were so many choices of frameworks around to use. So there is no consistent MVC framework, no routing, no templating (no ORM either, but that particular curse isn't as relevant here).
I'm going to have to keep things ticking over, squashing bugs and adding a few new features until a complete rewrite is usable, so I'm trying to breathe some sanity into things as I go along.
The easiest place to start seemed to be the views layer, for which I'm using TinyButStrong. An example of their sub-templates can be found here, but like I said, I think this is a very general question.
Things I've considered
With a more integrated framework I'd like to be able to do something like $view->add_js($foo), but transitioning to a full-blown framework is what other people are doing while I try keep the existing codebase seaworthy. There isn't even really enough consistent organisation of files to roll something like this by hand.
At the moment the best thing I can come up with is making a DOMDocument out of the view right before it's output and manipulating <link> and <script> tags at that point. I don't know if that's a bit crazy though. Given the generality of the problem I'd like to think that there's a known sensible way to go about it.
Many thanks for your input.
It's hard for the reader to know what can or cannot be done with your code base. A common way to handle this situation would be to pass parameters to the view template, and the template can then include conditional chunks or include sub-templates based on your parameters. This does not require a full-fledged framework, a stand-alone template engine should do. If your template engine supports inheritance there is a nice pattern for handling assets in your templates - check here for example http://symfony.com/doc/2.0/book/templating.html.
Manipulating the Dom for each request to handle this kind of thing seems bit unorthodox.
What you want in this situation is some form of template inheritance; that is, technology whereby a sub-template has access to areas in a 'parent' template, and can edit or replace content in those areas. Using this ability, CSS and JS required for a component included via a sub-template can be added in to the <head> element of the parent page.
In Twig, this is achieved using named blocks. First, you create your parent template (or layout, as it's called in Twig), e.g. index.html.twig. You include in it a named block like {% block myCss %}.
Next, to create a sub-template, you begin the template with the line {% extends ::index.html.twig %}. Then, the content of a block defined in the sub-template with the same name as a block in the parent template (in this case {% block myCSS %}) will get substituted into the parent template. To append rather than replace content in the parent template, use {{ parent() }} to include content already existing in the parent.
An example of this with code is available at the link given by #Basel Shishani. I've heard that Twig is modelled after Django, and template inheritance in Django looks very similar (with the exception of using {{ block.super }} instead of {{ parent() }}. There is a discussion of how to achieve the same ends in TinyButStrong.
As a wider point, the Assetic library looks like a very promising solution for managing CSS and JS assets, in order to avoid duplication (e.g. where the same JS file is required by multiple components/subtemplates), enable concatenation and minification of assets, and more. This presentation of its features gives more details.

Categories

Resources