I am a relatively new to Django, and have just run into a wall, but I am sure this will be a cake walk for you veterans out there. I have a list of items I am displaying in a table in a template. That is no problem I create an object (list of values) in my view send it to the template and render the table. However, I would like to also show on my template a bunch of count()’s displayed as links, that when clicked will further filter the list of items displayed. For example, I may have items in the list that cost between $25 and $50, my link would show that there are say 20 items that match that criteria. When the link is selected in sends a request to the url.py that in turn executes a view that further filters the queryset then renders template again.
How do I get the count() info to the template? I do not think I can send two separate lists (objects) to the template (at least I have not been able to figure out how yet). I think I need to get the counts at the view and then somehow append them to my list object, but I’m not sure how to do that and also, not quite sure how to parse those values in the template. I want the counts to show separate from the table generated from my list object, and I am somewhat concerned I’m going to mess up my table that is working fine now.
I would appreciate any suggestions you have about how to tackle this, and I would really appreciate code examples because I am still somewhat Python/Django code challenged.
You can send as many lists or objects to the template as you like. Template context is just a dictionary, and you can add items to it as necessary.
context = {
'list1': my_first_list,
'list2': my_second_list,
...
}
Your requirements are vague. Code helps. Also. Periods to end sentences help.
I think I need to get the counts at the view and then somehow append them to my list object
how to parse those values in the template.
Here's an approach. It doesn't use aggregate functions. They are more efficient, but also a little more difficult to understand. https://docs.djangoproject.com/en/1.3/topics/db/aggregation/
You have something like this in your view:
object_list = Model.objects.filter( some_attribute=some_value )
You do this in your form to see a count.
{% for obj in object_list %}
<tr><td>{{obj.name}}</td> <td>{{obj.related_set.count}}</td><tr>
{% endfor %}
This evaluates obj.related_set.count() for you. It's not the most efficient (aggregates are more efficient). But it's simple.
If you want a link, you'll replace the simple {{obj.related_set.count}} with something that includes a link
{{obj.related_set.count}}
Related
I've started using a rendered field in my django-haystack indexing to avoid database hits when a search is rendered. This is working well for the most part, but I have some runtime information (such as an edit button for staff) in the results as well that I'd like to splice in. A simplified example:
{{object.name}}<br/>
{% if user.is_staff %}
Edit
{% endif %}
{{ object.description}}
The user logic obviously can't be applied at indexing time so doesn't occur. Without using javascript hacks is there a way to splice some runtime output in amongst the pre-rendered text? I'm thinking it can be done by passing the rendered text with some formatting placeholders to a custom template tag, but I wonder if there's another way.
Edit: Perhaps multiple rendered, stored fields might be possible, covering the main fragments of the search result surrounding the logic parts, and then assembled at run time in the main results template. Would this work?
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'm new to Django and Python and I'm trying to understand how to accomplish paging without getting all the records from a QuerySet first. All the examples I've seen with QuerySets will get all the records first like below.
tickets = Ticket.objects.filter(site=site.id)
paginator = Paginator(tickets, settings.PAGE_SIZE)
This seems to make sense so that the Paginator will have a reference to how many pages it needs. However, this seems inefficient to get all the records for each page request. I know that QuerySets can be sliced to return a range of records.
How do I design my paging in order to only get the records pertinent for that page (slicing?), yet still have paging features?
Edit: Added template code that iterates.
{% for ticket in tickets.object_list %}
{{ ticket }}<br/>
{% endfor %}
Underlying queries for the QuerySet objects are not executed until you explicitly evaluate them. Explicit evaluation occurs whenever you iterate through them, which includes calling str() or unicode().
Thus, the above code snippet is indeed efficient. The line tickets = Ticket.objects.filter(site=site.id) creates a new QuerySet, but the query isn't evaluated yet.
For the same reason, stuff like Model.objects.filter(foo).filter(bar).order_by(baz)... doesn't execute a single SQL query.
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
What is the correct way to do conditional formatting in Django?
I have a model that contains a date field, and I would like to display a list of records, but colour the rows depending on the value of that date field. For example, records that match today's date I want to be yellow, records that is before today I want green and ones after I want red.
Somewhere in Django you will need to do that comparison, comparing the current date with the date in the record.
I can see three different places that comparison could be done:
Add a method to my model, for example, status(), that returns either 'past', 'present', 'future' and then use that in the template to colour the rows.
In the view instead of returning a queryset to the template, pre-process the list and compare each record, build a new dict containing the 'past', 'present' and 'future' values to be used in the template
Create a new template tag that does the comparison.
Which of these methods is the correct Django way of doing it? It sounds like conditional formating is something that would come up quite often, and since you can't do arbitrary comparisons in the template some other solution is needed.
The same would apply for simpler formatting rules, for example, if I wanted to display a list of student grades, and I wanted to make the ones higher than 80% green and the ones below 30% red.
I'm a big fan of putting ALL "business" logic in the view function and ALL presentation in the templates/CSS.
Option 1 is ideal. You return a list of pairs: ( date, state ), where the state is the class name ("past", "present", "future").
Your template then uses the state information as the class for a <span>. Your CSS then provides the color coding for that span.
You are now free to change the rules without breaking the template. You can change the CSS without touching HTML or Python code.
{% for date,state in the_date_list %}
<span class="{{state}}">date</span>
{% endfor %}
I had a very similar requirement; as this is pretty connected to the business logic, I have added a model method to manage this kind of information, to be used then in the template:
{% if not bug.within_due_date %}bgcolor="OrangeRed"{% endif %}
It could also be obtained through a template tag or filter; but in my case, I felt the best place for the logic was inside the model; I would suggest you analyzing it in the same way.
Since you are doing static comparison (no queries needed), you should go for the most DRY and easy to implement option. In this case, I would go for option 4, make a template filter. Then you could do value|filter to get the class you would need to set the background colour. Template filters are actually a bit simpler than template tags to implement.
you can also take a look at Django's reference for built in Formatting and Filtering tags. It sure has what you are looking for and more and it's a good link to have bookmarked.
You can take a look at it here.