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.
Related
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.
I know of with, and I know you can write your own template tags for this purpose, altering the context variable. However, given these circumstances:
Cannot alter an application you are reusing, and do not want to "monkeypatch" its views.
You have multiple isolated blocks in a given template, whatever.html, and, say, a blog_post context variable that has a categories member. You reference this 'categories' field multiple times in the template differently, for instance, you only want the first element in one place/block, and then you iterate them all in a different spot in the template.
You want to avoid duplicating queries altogether.
You do not want to enclose everything with a 'with'/'endwith' block.
What would be the most efficient way to go about this?
Well you can write a middleware for the specific view and alter process_template_response context just before it renders. I think that will help.
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.
This is more of a best-practices question, and given that I'm quite tired it mightn't make much sense.
I've been putting together a blog app as a learning experience and as an actual part of a website I am developing.
I've designed it like most apps so that you can list blog posts by multiple criteria i.e.
/blog/categories/
/blog/authors/
/blog/tags/
/blog/popular/
etc.
On each page above I also want to list how many entries are a part of that criteria
i.e. for "categories", I want /blog/categories/ to list all the different categories, but also mention how many blog posts are in that category, and possibly list those entries.
Django seems to give you lots of ways of doing this, but not much indication on what's best in terms of flexibility, reusability and security.
I've noticed that you can either
A: Use generic/very light views, pass a queryset to the template, and gather any remaining necessary information using custom template tags.
i.e. pass the queryset containing the categories, and for each category use a template tag to fetch the entries for that category
or B: Use custom/heavy views, pass one or more querysets + extra necessary information through the view, and use less template tags to fetch information.
i.e. pass a list of dictionaries that contains the categories + their entries.
The way I see it is that the view is there to take in HTTP requests, gather the required information (specific to what's been requested) and pass the HTTP request and Context to be rendered. Template tags should be used to fetch superflous information that isn't particularly related to the current template, (i.e. get the latest entries in a blog, or the most popular entries, but they can really do whatever you like.)
This lack of definition (or ignorance on my part) is starting to get to me, and I'd like to be consistent in my design and implementation, so any input is welcome!
I'd say that your understanding is quite right. The main method of gathering information and rendering it via a template is always the view. Template tags are there for any extra information and processing you might need to do, perhaps across multiple views, that is not directly related to the view you're rendering.
You shouldn't worry about making your views generic. That's what the built-in generic views are for, after all. Once you need to start stepping outside what they provide, then you should definitely make them specific to your use cases. You might of course find some common functionality that is used in multiple views, in which case you can factor that out into a separate function or even a context processor, but on the whole a view is a standalone bit of code for a particular specific use.
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.