(Django) Showing simple stats about model instances - django

What would be the correct approach to create a "stats block" which could be used easily?
I've now created a simple page template and view function which returns a list of stats e.g. users and user count by calling User.objects.all().count()
How should this be implemented to be able to include these stats in any template? And perhaps with different styles such as list, inline, bootstrap panel etc?

If you want it in any template, you probably want to write your own custom template tag. This is the relevant Django documentation: https://docs.djangoproject.com/en/2.2/howto/custom-template-tags/#writing-custom-template-tags
Your tag will probably return minimalist data: just the result of queryset.count(). The template that you are rendering will place this number in the relevant html context.

Related

Where to put DB-accessing template helper functions in Django

So I have a search page with result table. I have a drop down that's a filter from the DB. Instead of calling and populating this drop-down field filter at my view/index() method, can I just call a helper function that returns this list from the DB and populates the drop down at the template level?
I know about context_processors and my understand is that it's for the entire site, but I want this DB call to only happen on this particular page and no where else?
What do call this so I can try to find it in django docs.
Much Thanks
edit: to clarify more: the result table contains movies and drop-down filter is movie types (actions, adventure, thriller, etc). This list is made up from a "SELECT DISTINCT type FROM movies" query.
The Django equivalent of helpers is custom template tags, and it's certainly appropriate to put db-accessing code there.
However, if it's only for a single page, I'm not sure why you wouldn't do it in the view.

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

What is the purpose of django tempate tags in the MVC model?

It is my understanding that template tags are a way to organize presentation logic, is this correct?
What I want to do is load/read a bunch of my model objects, but show them in different areas of the template according to a filter.
The first thought was to implement a tag get_myobjects_by_filterx but then I have to implement it for each filter I have, and I would use it by calling the tag on the areas of my template where I want them to show up.
So the second thought was to move the filterx into the tag itself, so the call would be get_myobjects_by "X" (passing the filter as string) then in the tag filtering and returning. Is this the prefered way? What if I need to pass another object not just a string?
Could I use a filter instead?
Little more detailed what I want to do: Load a kind of my objects and filter it by some of its fields, depending on which filter is applied, show it in different areas of my template. For example I want "if objects filtered by X show all of those in the column x else in column y and so on".
How do I solve this kind of question with django?
Thanks.
As far as my understanding goes, template tags are nothing but some python functions which can be used inside the templates. Because a django template is not your normal python program.

Forwarding a Django template dictionary to another template?

Is it possible to reuse a template dictionary in another view ?
For instance, imagine a view performs a search on the db and provide the search results in a dictionary to a template. The template displays the first 10 results and has a link to display all the results in another page.
Is it possible to forward the template dictionary containing the search results to avoid having to perform the same search again ?
Not really. You can't preserve anything across page views - except by storing it somewhere, eg in the session. You couldn't put it in the template itself, as that would then need to be sent back to the server via a POST for the next request.
In any case, there's not much need to do this. If you use the built-in Paginator class to paginate your search, Django will automatically use LIMIT and OFFSET in the query so that only the objects you're actually displaying will be queried.

How can I pass a standard, static variable from all views in Django?

I'm working on a blog application, and I want to have a sidebar that includes a list of all the months the blog has been in existence, to provide links to archives pages. Moreover, I'd like to make this automatically update when the month changes, rather than hardcoding it in the template. Of course, as far as I can tell, this means that I'll have to calculate the list of months in every view, and pass it into every template from every view.
I'd like to avoid this, if possible. Is there a way to calculate the list once and automatically apply it to every template, without having to explicitly pass it into the template from every view?
There are a few possible solutions to your problem.
If you really want to have this on every page on your site a context processor is probably your best choice. Context processors are basic way to inject data into all template contexts. Be aware however that the context processor will be called on every request.
An alternative solution would be to create a custom template tag and use it on a shared base template for all of the pages you wish to have your sidebar. Template tags are a bit more complex to create but they are more flexible.
With either solution you should also look at Django's cache framework. The cache framework makes it pretty easy to temporarily store your calculated values for a while to save some work on each request.
You want a template context processor
Django - having middleware communicate with views/templates
http://docs.djangoproject.com/en/dev/ref/templates/api/?from=olddocs#id1
Django's template inheritance should cover this. You could create a base template that handles your sidebar functionality. Your other views extend this template.
Template Inheritance:
http://www.djangobook.com/en/1.0/chapter04/#s-template-inheritance
A combination of custom template tags as mentioned previously and template fragment caching should do the trick.