Django and haystack with whoosh, search formatting - django

Im trying to format my search page so that it will split my results by model_name.
The problem i've got is that my heading get repeated because its inside the for loop. Is there any way to re-write this code so that the heading is only shown once?
Thanks
{% for result in page.object_list %}
{% ifequal result.model_name 'post' %}
<h3>Videos</h3>
<p>
{{ result.object.title }}
</p>
{% else %}
<h3>Photos</h3>
<p>
{{ result.object.title }}
</p>
{% endifequal%}
{% empty %}
<p>No results found.</p>
{% endfor %}

Check ifchanged tag.
Usual algorithm in such cases is:
1) Sort results on heading field
2) Use ifchanged tag.

Related

If statement in my Django template...Is there a better way?

In my Django template: I'm trying to add an extra div around my for loop only if the length of the data being passed to the template is 3. This is what I'm trying right now but it seems like there could be better way than doing two if statements to check for the length:
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% endif %}
{% for item in items %}
.......
{% endfor %}
{% if items|length == 3 %}
</div> //close .three-item-wrap
{% endif %}
you can try like that
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% for item in items %}
.......
{% endfor %}
</div>
{% else %}
#another logic goes here
{% endif %}
if you want know more refer the docs django if tempalate
I think better way would be to make single if statement check. Just like this:
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% for item in items %}
.......
{% endfor %}
</div>
{% else %}
{% for item in items %}
.......
{% endfor %}
{% endif %}
This way is better because of Django render engine, which firstly check if statements and then do for loop.
And if something crash in your code, div will be without closing tag </div>. Instead in my code there is no option for div to be without closing tag.

work around setting variables in django templates

I have this code that I used from twig to display sections according to the same date.
I'm trying to use the same code in Django but I can't set variables in its template system. What is the sane way to do this? The correct way? How do people tackle such a problem?
{% set date = "prout" %}
{% for article in articles %}
{% if article.date != date %}
{% if date != "prout" %}
</ul>
</section>
{% endif %}
{% set date = article.date %}
<section class="row">
<h2>{{ article.date }}</h2>
<ul>
<li>+ {{ article.titre }}</li>
{% else %}
<li>+ {{ article.titre }}</li>
{% endif %}
{% endfor %}
</ul>
</section>
The closer concept to 'set' variables is with tag. Quoting Built-in template tags and filters django docs:
with
Caches a complex variable under a simpler name. This is useful
when accessing an “expensive” method (e.g., one that hits the
database) multiple times.
For example:
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}

Django template: check for empty query set

Is there a way to check for an empty query set in the Django template? In the example below, I only want the NOTES header to be displayed if there are notes.
If I put an {% empty %} inside the "for" then it does display whatever is inside the empty tag, so it knows it's empty.
I'm hoping for something that does not involve running the query twice.
{% if notes - want something here that works %}
NOTES:
{% for note in notes %}
{{note.text}}
{% endfor %}
{% endif %}
Clarification: the above example "if notes" does not work - it still displays the header even with an empty query set.
Here's a simplified version of the view
sql = "select * from app_notes, app_trips where"
notes = trip_notes.objects.raw(sql,(user_id,))
return render_to_response(template, {"notes":notes},context_instance=RequestContext(request))
Edit: the view select selects from multiple tables.
Have a look at the {% empty %} tag.
Example from the documentation
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>
Link: https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#for-empty
If you are interested in a table, or some kind of heading if there are results, add the forloop.first:
{% for athlete in athlete_list %}
{% if forloop.first %}
Athlete Name:
{% endif %}
{{ athlete.name }}
{% empty %}
Sorry, no athletes in this list.
{% endfor %}
Try {% if notes.all %}. It works for me.
In your view check whether notes is empty or not. If it is then you pass None instead:
{"notes": None}
In your template you use {% if notes %} as normal.
It's unfortunate that you're stuck using a raw query set - they're missing a lot of useful behavior.
You could convert the raw query set into a list in the view:
notes_as_list = list(notes)
return render_to_response(template, {"notes":notes_as_list},context_instance=RequestContext(request))
Then check it as a boolean in the template:
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
You could also make it happen without conversions using forloop.first:
{% for note in notes %}
{% if forloop.first %}
Header
{% endif %}
{{ note.text }}
{% endfor %}
What about:
{% if notes != None %}
{% if notes %}
NOTES:
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
{% else %}
NO NOTES AT ALL
{% endif %}
Your original solution
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
Works now with Django 1.7 and thanks to QuerySet caching, it does not cost and extra query.
Often the right way to do this is to use the {% with ... %} tag. This caches the query so it runs only once and also gives you more flexibility with your markup than using {% empty %}.
{% with notes as my_notes %}
{% if my_notes %}
<ul>
{% for note in my_notes %}
<li>{{ note }}</li>
{% endfor %}
</ul>
{% else %}
<p>Sorry, no notes available</p>
{% endif %}
{% endwith %}
With this particular example I'm not sure how useful it is but if you're querying Many-to-Many field, for instance, it's likely what you want to do.
Use {% empty %} in django templates
{% if list_data %}
{% for data in list_data %}
{{ data.field_1 }}
{% endfor %}
{% else %}
<p>No data found!</p>
{% endif %}
We can write above code with {% empty %}.
{% for data in list_data %}
{{ data.field_1 }}
{% empty %}
<p>No data found!</p>
{% endfor %}

How to striptags in haystack highlight?

I am using django-haystack. In the highlight haystack provides, how can i render tags or striptags in the result.
{% for text in result.highlighted.text %}
<blockquote>{% highlight text with query %}</blockquote>
{% endfor %}
I need to do something like this:
{% for text in result.highlighted.text %}
<blockquote>{% highlight text|striptags with query %}</blockquote>
{% endfor %}
But this is not working, please suggest something.
Thank you in advance.
Like this:
{% for text in result.highlighted.text %}
<blockquote>
{% with text|striptags as stripped_text %}
{% highlight stripped_text with query %}
{% endwith %}
</blockquote>
{% endfor %}
https://docs.djangoproject.com/en/def/ref/templates/builtins/#with

Django, loop over all form errors

At my template, I want to iterate through all form errors, including the ones that are NOT belonging to a specific field. ( which means for form.errors, it should also display for __all__ errors aswell)
I have tried several versions, Ie:
<div id="msg">
{% if form.errors %}
<div class="error">
<p><span>ERROR</span></p>
<ul>
{% for key,value in form.errors %}
{% for error in value %}
<li>{{ error }}</li>
{% endfor %}
{% endfor %}
</ul>
</div>
{% endif %}
</div>
Still no achievement, I will be greatful for any suggestion.
Form errors in Django are implemented as an ErrorDict instance (which is just a subclass of dict with extras). Try a slight adjustment to your template for loop syntax:
{% for key, value in form.errors.items %}
Are you, by any chance, looking for form.non_field_errors? That is how you would get access to the errors that aren't associated with a particular field.
{% if form.non_field_errors %}
<ul>
{{ form.non_field_errors.as_ul }}
</ul>
{% endif %}
Check the forms.py test suite as well for another example. Search for form.non_field_errors