I am a django newbie and in creating my first project I have come to realize that a lot of my boilerplate code (the lists on the side of my page). I have to recreate them in every view and I am trying to stick with DRY but I find myself rewriting the code every time. Is there a way to inherit from my base views and just modify a few objects?
Thanks,
James
Yes, you'll want to look into template inheritance, which lets you share common elements between templates, and the {% include %} template tag, which lets you create reusable template "snippets" that can be included in other templates.
Edit: Re-reading the question, it sounds like you're talking about boilerplate code that you have in your view functions/methods that you're using to generate context shared by multiple templates. In that case, mipadi's answer is the right one: Look into context processors.
You might want to use a context processor for this work.
For the lists of recent articles etc, custom template tags are the thing you need. Whereas a context processor will populate your context with the lists automatically, a template tag can actually do that plus create the whole HTML markup for the column itself.
For large blocks of static html that reappear consistently you can use the include template tag:
{% include 'static/some_file.html' %}
The includes are stored in your template file system, just like templates.
If you don't decide to use context processor for some reasons (this solution looks reasonable here) you can always encapsulate some common logic into util functions and use them in your views.
You can also take a look at Generic views - this is a good way to 'stay DRY' with your code
Related
I am learning Django and I programming a CRUD for various objects. Currently I need to generate three templates per object: one for creation, one for update and one for a list. Look at how many templates I got in the picture.
The process is becoming painful.
What I am doing wrong and how to correct it?
Thanks.
From your comment:
The problem is that If I need to make a change, for example, add a new button, I have to make it in all the templates.
That sounds wrong. Either a button belong to one type of thing and then it should only exist in that template, or it should be on every page and then it should be in the base template.
You can make one template with your basic page layout (including such buttons), and have "blocks" in them that are then filled out by each template that extends the base template.
See the Django documentation about template inheritance.
Also, I think that in most cases the "create" and "update" pages are going to be extremely similar; usually they use the same template, one with data already filled in, the other without.
You could have a base template, then a generic list template and a generic edit/create template, with templates for each type of thing extending the list and the edit templates to fill in only the relevant fields.
Also, maybe you use HTML that is close enough to what the Django forms can render themselves. Then as long as you call the edit/create form the same in each of your views (like "form"), the template can just render the form and they can all use the same template.
If you're building a big web-app then this is normal for templates to be more.
Heavy (big) web-app means = more templates + more code + more time + more features
I'm in the process of delving into Django into a little more depth - and I now have certain blocks around my website which are recycled, but not necessarily suited to a being placed in base.html and then sprinkled with {% extends /root/to/base.html %}.
So, I have a bespoke widget I have created which is utilised on certain pages but in different configurations, is it best to register and inclusion tag and reference the template you want to accompany those stored variables and arrays/lists/dictionaries etc..
For me it seems easier to define tags and then dot these around where I need them and just make edits to the template that is registered with that tag method? But is this the accepted Django standard?
In Django
a "view" is a callable that is responsible for handling a request and returning a response,
a template tag is a piece of code that will be executed in the context of rendering a template and will either push something in the template's context or render some text or markup.
Oranges and apples, really, and it should be quite clear when you want a view and when you want a template tag.
And yes, using inclusion tags (or a full-blown custom tag using a template to render some data) is "an accepted Django standard" - actually that's exactly what template tags are for.
I have a view that perfectly fits the ListView in Django. Like this:
url(r'^$',
ListView.as_view(
queryset=Poll.objects.order_by('-pub_date')[:5],
context_object_name='latest_poll_list',
template_name='polls/views/index.html')),
However I on the page of the view I also would like to display content from another model. This model contains only one row of data. It's sitewide and contains the footer-text page-title etc.
What's the best solution for this? Ideally I'd like to keep the generic-model approach.
There are several methods that will solve this issue. The view is definitely not the correct place.
Template Tags
One way to use template tags is as mini-views. Whether you are requesting data from another model, or rendering an included template.
Because you can also pass parameters into the template tag, they can be customized by the context.
Context Processors
For simpler information,context processors work well. I wouldn't get too complicated with the data, as it is global and can slow down every request.
On an aside, I would also question your one-row model. My guess is that this is to allow user editing. If users access it, expect every possible way of screwing it up. For example, adding more rows. There are several Django applications for managing user-editable settings that might be useful. If the data isn't going to change often, I would make it an actual setting, or put it in a template snippet and {% include %} it.
I have a footer included in my base template with:
{% include "footer.html %}
I need to show it in every page. But the footer has several statics which needs to be calculated with several queries each time the page loads.
As far as I know, this include cannot run queries because any views is called. And I don't want to replicate the query for that in all my views, I think it's a dirty solution.
What's the best practice in this case? I think it's a quite common problem.
Although context processors are good for including standard things in every template, I suspect for your purposes a custom template tag that renders the entire footer would be a better bet - probably an inclusion tag would do the job.
If statistics are global (not something related to specific page/request) you can implement your custom context processor which can calculate statistics and add corresponding variables in the context. That context variables/dict can be used by footer.html to put the statistics.
Refer Writing custom context processor
You can use context processors to run your queries in all views and update your context with necessary data.
What about creating a Context Processor, and return the query from there ?
The result will be available in every view, if that's what you desire ?
You should write context processor to work this out :
writing context processors
Another option not mentioned here so far are custom template tags. Depending on what exactly you want to do a context processor might be overkill.
I'm new to Django and coming from Rails, so that may explain my odd questions below:
I have a main layout that has a sidebar that lists the latest updates to the site. That main layout is used for every page in my webapp so every template that is created extends main.html.
For the latest updates section, I just want to get the last 5 updates from posts to the web app every time a page is rendered. I thought about making the sidebar do this through an ajax call once the page is loaded, but I thought this may not be my best option.
I also considered creating a tag to do this for me and then just calling the tag inside of main.html. This is simple enough, but I'd have to write a lot of HTML inside of the tag code, which seems to be a little annoying (a lot of string appending and such, unless I'm wrong and there is a better way?)
I have read about Context Processors. This seemed to be exactly what I wanted, but it appears this may cause another issue where I have to pass a context_instance to every single render_to_response? This appears to be a lot of code repeat and I'm trying to avoid that if possible. Is there a way to just make render_to_response always take the RequestContext object without always having to specify it?
Are there any other ways to achieve having some code run for every view and eliminate the need to always pass data to a view?
Django 1.3 added the render shortcut which is the same as render_to_response but with RequestContext automatically used.
Templates is a appropriate place for this: the variant with custom tag and template inheritance is simple and convenient. To avoid string appending use mini-template just for your tag: it is called inclusion tags.
I would definitely go for the Ajax call, it is as simple as to create an small view which queries the model for the 5 latest posts, serializes them into json or xml data, and returns them in your HttpRequest object.
You can use direct_to_template instead of render_to_response.