Here is a Django template.
{% for balance in balances %}
{{ balance.amount }}
{% endfor %}
{% for price in price %}
{{ price.amount}}
{% endfor %}
I would like to show multiple values in Django template like one after another. I also need to print the page number.
For example, 1,2,3,4 page for balance and 5,6,7 is used for the price.
So is there any way I can print it?
For the first request, explain yourself better.
For paging of one or more lists of objects there is already a Class Based View that allows it. The following documentation explains everything clearly:
https://docs.djangoproject.com/en/4.0/topics/pagination/
Related
I'm using django-haystack for a search page on my site, and I want to order all the results by their content type. Is there a way I can do that?
To make it simpler, suppose I have a single application and several classes.
Thanks in advance
Not sure what you mean by content type, but if you are talking about group by models, I have this working
{% with page.object_list as results %}
{% regroup results|dictsort:"verbose_name_plural" by verbose_name_plural as grouped_objects %}
{% for ct in grouped_objects %}
{{ ct.grouper }}
{% for result in ct.list %}
<p>
{{ result.object }}
</p>
{% endfor %}
{% empty %}
<p>No results found.</p>
{% endfor %}
{% endwith %}
from How to order search results by Model:
You can do
SearchQuerySet().order_by('django_ct').
As a warning, this throws out
relevancy. The only way to keep
relevancy & group by model is either
to run many queries (one per model -
usually performant thanks to query
caching) or to run the query and
post-process the results, regrouping
them as you go.
from searchindex api:
Haystack reserves the following field
names for internal use: id, django_ct,
django_id & content. The name & type
names used to be reserved but no
longer are.
You can override these field names
using the HAYSTACK_ID_FIELD,
HAYSTACK_DJANGO_CT_FIELD &
HAYSTACK_DJANGO_ID_FIELD if needed.
I'm relatively new to Django and as a test of my knowledge I'm trying to set up a project where it displays a list of games between anchor tags, when one of the game tags is clicked on, it pulls information about that game from a model using the ID (primary key) relative to that name. For instance the first games ID would be 1 and so on.
However, I am uncertain as to how to approach building a view for this. The only way I was able to get information from a template before was from user input (input tag) and then using request.GET to take the information from the input.
So far in this project, anchor tags are linking to a different URL which has the view which gets the information based on the id, then it should refresh the page and the information should display. Everything should be easy, but I'm just having trouble thinking of a way to get the id of the game based on which link is clicked. Is there a way I can simply set the value of this ID somewhere and reference it in the view, or rather pull the id of the game based on which link is clicked?
Code:
{% extends "base.html" %} <!-- Extends the base models html design-->
{% block title %}Arcade{% endblock %}
{% block content %}
{% if games %}
<p>Found {{ games|length }} game{{ games|pluralize }}</p>
{% for game in games %}
<li>{{ game.game_name }}</li><!--Game Link->
{% endfor %}
{% else %}
<p>There are currently no games in the database.</p>
{% endif %}
{% if results %}
{% endif %}
{% endblock %}
I hope I did an adequate job explaining this problem.
To simplify it further: How do I pull any kind of value from a template?
Thank You
Keith
This is simple. In each iteration of your for loop, you have an object called game, which is presumably a model instance. So you can just do:
<li>{{ game.game_name }}</li>
Or, even better, use the reverse URL functionality:
<li>{{ game.game_name }}</li>
You should look at using AJAX for this.
When the user clicks a tag, have the page asynchronously GET or POST to your django backend. If you want to GET, write a url to the effect of
^/data/game/(\d+)
then grab the id, get your model instance, and return some json or xml.
One very annoying thing with strict MVC is that you can make the smallest processing in template. While it's usually a good practice, in this case it gets in the way:
I make a for loop on a queryset of a lot of objects and display some attributes;
Attributes are properties, making heavy processing (I don't want to trigger them twice).
At the end I need to display a total of the value of these attributes.
I now I have to do the sum once in the view, then reloop (and call the properties again) to display. I can improve that by loopring once in the view and caching the results, but then I get more code just to bypass this limitations, and I use more memory.
At this stage of the project, it's not THAT a big deal. Performance is not the issue yet at all. But I really like to know is there is a solution for this.
My best bet is to write a template tag that does the job, but it's such a chore :-) Do you know somebody that would have done that already?
E.G:
Ideal, it sould be something like:
{% for object in object_list %}
- {% sum_in_and_print object.property total %}
{% endfor %}
total {{ total }}
that would display:
- 2
- 3
- 1
total 6
I don't see how it's a chore. Check if the destination variable is in the context, and if not, initialize it with an empty-constructed object of the class of the first element in the list, then accumulate.
As an alternative to calculating the sum in a view or template, what about QuerySet.Annotate(total_x=Sum('x')), to have the database take care of the calculations?
Aside: I believe trying to solve the actual problem sometimes warrants not answering the direct question when there is not an obvious answer.
I'ts quite hard tag to write nicely. You will have to take care if evaluation order is ok (sum may be displayed above data). That you can have many sumup sections (maybe data too). You will need probably following structure:
{% raport %}
{% sumup %}
...
{% endsumup %}
{% data %}
...
{% enddata %}
{% sumup %}
...
{% endsumup %}
{% endraport %}
EDIT:
Also you will have hard times, to parse multilevel structure:
{% raport %}
{% sumup %}
...
{% endsumup %}
{% data %}
{% raport %}
{% sumup %}
...
{% endsumup %}
{% data %}
...
{% enddata %}
{% sumup %}
...
{% endsumup %}
{% endraport %}
{% enddata %}
{% sumup %}
...
{% endsumup %}
{% endraport %}
I don't know what project your're developing, but if you already require users to have JavaScript, you may check jQuery.calculation plugin. This is a great tool to shift all dumb calculations to the client side.
Look into a different templating system like Mako. Mako especially allows full python code to run within the template.
Is there a compelling reason you're not doing this in the view?
What could be easier than:
total = sum([o.property for o in object_list])
Even if your goal is to use generics, you can always wrap it in a view function.
Let me add that I think the functionality you specifically want: to output a variable and add it to some arbitrary variable -- is such a unique one that absolutely you'll want to write your own template tag for it.
Fortunately, this is very easy.
Update
As I said in the question the property
trigger HEAVY processing. I don't want
to trigger them twice...
So you could try this instead:
rendered_object_list = []
for o in object_list:
rendered_object_list.append({
'field1': o.field1,
'field2': o.field2,
'property': o.property
})
total = sum(o['property'] for o in rendered_object_list)
You process it once, in the view, then when you output it in the template, it's a dictionary, with everything in the dictionary already processed.
I find django's template language very limiting. Following along with django's DRY principle, I have a template that I'd like to use in many other templates. For example a patient list:
{% for physician in physicians.all %}
{% if physician.service_patients.count %}
<div id="tabs-{{ forloop.counter }}">
{% include "hospitalists/patient_list.html" %}
</div>
{% endif %}
{% endfor %}
The problem is that the patient_list template is expecting a list of patients named patients. How can I rename physician.service_patients to patients before including the template?
Thanks,
Pete
Use the with tag:
{% for physician in physicians.all %}
{% if physician.service_patients.count %}
{% with physician.service_patients as patients %}
<div id="tabs-{{ forloop.counter }}">
{% include "hospitalists/patient_list.html" %}
</div>
{% endwith %}
{% endif %}
{% endfor %}
You might also upgrade to creating a custom tag:
{% for physician in physicians.all %}
{% if physician.service_patients.count %}
{% patient-list physician.service_patients %}
{% endif %}
{% endfor %}
Although custom tags involve writing Python code, there are shortcuts that make it easy to use an existing template file as a tag: Django Inclusion Tags
When you have "functionality" (specifically an if-condition) inside a loop, you have an opportunity to move this into the view function.
First
This construct
{% for physician in physicians.all %}
{% if physician.service_patients.count %}
{% endif %}
{% endfor %}
Is so common that you have several ways to avoid it.
Change your model. Add a patients" method and use it instead of the default query set that you get with a on-to-many relationship. This method of your model has theif service_patients.count` test, removing it from your template.
This eliminates the {% if %} from your template, reducing it to {% for %} and the actual HTML, which cannot easily the eliminated.
Change your view function. Write a few lines of code to create a list of physicians with service_patients instead of a simplistic collection of physicians. This code in your view function has the if service_patients.count test, removing it from your template.
This eliminates the {% if %} from your template, reducing it to a {% for %} and the actual HTML, which cannot easily be eliminated.
The point is to get rid of the {% if %} so that you're simply cutting and pasting the {% for %} and the actual HTML. By keeping your template to just the HTML (which cannot be eliminated), the only overhead is the {% for %}
Second
It appears that you want to reuse an {% include %} construct in slightly different contexts.
It's not at all clear what the problem with this {% include %} file is. It is "expecting a list of patients named patients" seems superficially silly. Fix it, so it expects physician.patients.
Perhaps you want to use this same list twice. Once with a list called 'patients' and once with a list called 'physician.patients'. In this case, consider (a) simplifying or (b) writing a template tag.
It appears that you have a patient list that is sometimes a stand-alone page, and other times is repeated many times on a much more complex page. Repeating a list of details embedded in some longer list is not really the best page design. Django doesn't help you with this because -- frankly -- it's not easy for people to use. Hence option (a) -- consider redesigning this "patient list within a physician" list as too complex.
However, you can always write a template tags to create really complex pages.
Summary
There's a really good reason why the Django template language has limited functionality. All of your functionality should be either an essential feature of your model, or a feature of the current application that uses the model.
Presentation is simply the translation of objects (and querysets) into HTML. Nothing more
As way, you can try to use in quality templating language jinja. It is more flexible.
Am working with django Publisher example, I want to list all the publishers in the db via my list_publisher.html template, my template looks like;
{% extends "admin/base_site.html" %}
{% block title %}List of books by publisher{% endblock %}
{% block content %}
<div id="content-main">
<h1>List of publisher:</h1>
{%regroup publisher by name as pub_list %}
{% for pub in pub_list %}
<li>{{ pub.name }}</li>
{% endfor %}
</div>
{% endblock %}
but when I run "http://127.0.0.1:8000/list_publisher/" the template just prints the page title with no error! What am I doing wrong?
A few suggestions:
check that your base_site.html does define a {% block content %}{% endblock %} section to be refine by your my list_publisher.html
check the cardinality of your list: {%regroup publisher by name as pub_list %}{{ pub_list|length }}. That should at least display the length of your list. If is is '0'... you know why it does not display anything
check that your list is indeed sorted by name before using regroup, or use a {% regroup publisher|dictsort:"name" by name as pub_list %} to be sure
If the length is '0', you have to make sure publisher is defined (has been initialized from the database), and sorted appropriately.
In other word, do you see anywhere (in your template or in the defined templates):
publisher = Publisher.objects.all().order_by("name")
?
(again, the order by name is important, to ensure your regroup tag works properly)
Good answer by VonC.
A quick and dirty way to look at pub_list is to stick [{{pub_list}}] in your template. I put it in square brackets in case it's empty. BTW, you may get something that looks like [,,,,,]. This is because object references are wrapped in <> and your browser is going WTF? Just do a View Source and you'll see the full result.