Django pagination and Ajax queries - ajax

In Django it is quite straight forward to implement a pagination to display the query items on several pages. It is also quite straight forward to utilize Ajax to update only the bits of the page that really have changed, rather than loading the entire page every single time. However I found it a bit problematic when the two are combined.
In the example below the search results shall be shown in the appropriate result_list.html.
<form id="search-form" method="get" action=".">
{{ form.as_p }}
<input type="submit" value="search" />
</form>
<div id="search-results">
{% include "result_list.html" %}
</div>
result_list.html:
{% if sales_items %}
{% for item in sales_items %}
<li>
<ul>
Search Result...
</ul>
</li>
{% endfor %}
{% if show_paginator %}
<div class="paginator">
...
(Page {{ page }} of {{ pages }})
</div>
{% endif %}
{% else %}
{% trans 'No Items found.' %}
{% endif %}
This solution works very nicely. Because everytime I search (through ajax) for something the result_list.html including the pagination are refreshed.
Problem:
But now if I had a table instead I couldn't use this approach anymore.
<table class="table">
<thead>
<tr>
<th>...</th>
</tr>
</thead>
<tbody id="search_result">
{% include 'calls_list.html' %}
</tbody>
</table>
The page bit that is required to be refreshed is just between the <tbody> tag. Hence Calls_List.html returns only <tr> and <td> tags that is understood by a <tbody>. I simply couldn't paste the paginator code in there as well (unlike the above example):
{% if show_paginator %}
<div class="paginator">
...
(Page {{ page }} of {{ pages }})
</div>
{% endif %}
... since the table's tbody isn't expecting to find a div element there.
Unless I do a second round trip to the server to pull the pagination code separately. I couldn't find a clean solution for this.
Have you been in the same situation, How did you solve this please?
Many Thanks,

One solution would be that you put the pagination part in a <tr> but change the visualization as you would like (e.g. only 1 <td> or spanning multiple columns etc.)
Another solution would be you change your Calls_list.html to return complete <table> tag and put pagination part out of table in a separate <div>.
Third option could be return JSON of rows data along with pagination data. Then just update the existing table rows and pagination html.

Related

How to display data from Jekyll data file based on current page variable

The Problem
I have a div on my Jekyll site where I would like to display data that is generated from _data/book-data.yml, for example:
- name: johnson-everything-under
title: Everything Under
author: Daisy Johnson
publisher: Faber & Faber
pub-date: 12/12/2012
- name: johnson-train-dreams
title: Train Dreams
author: Denis Johsnon
publisher: Granta
pub-date: 01/01/2001
I'm trying to find a way to display the data that corresponds to the relevant page (each book entry has a different page), and I thought maybe this would be possible if the name key corresponds to the page.url, or some other page variable.
What I've tried
On a working page, I have an include which contains the following HTML:
<div class="book-meta">
{% if page.category == "reviews"%}
<div class="book-thumbnail">
<img class="post-thumbnail-lg" src="{{ site.baseurl }}/assets/images/{{ page.thumbnail }}" alt="{{ page.thumbnail }}">
</div>
{% for book in site.data.book-data %}
<div class="book-details">
<ul class="book-meta-list">
<li class="book-meta-item"><p>{{ book.author }}</p></li>
<li class="book-meta-item"><p><em>{{ book.title }}</em></p></li>
<li class="book-meta-item"><p>{{ book.publisher }}</p></li>
<li class="book-meta-item"><p>{{ book.pub-date }}</p></li>
</ul>
</div>
{% endfor %}
{% endif %}
</div>
The CSS is not important, but as it is currently the output of the above HTML is:
Desired output
As you can see, the output contains both the blocks of metadata from the .yml file. I would like to find a way so that only the relevant block of data (the first block in this instance) is displayed:
Potential solution(s)
I thought that there might be a way of matching a page.variable to the YAML block name so only the right book data gets output. Something along the lines of:
{% assign url_substring = page.url | split, '/' | last %}
// url_substring = johnson-everything-under
{% for book in site.data.book-data %}
{% if url_substring == book.name %}
// = true
<p>{{ book.title }}<p>
{% endif %}
{% endfor %}
Other than the fact that I can't get this to work properly, I can also see that the liquid tag {{ book.title }} has no way of knowing which book title to output, even if the page.url matches.
I'm not sure if I'm on the right track here, so if anyone has any other suggestions on how this might be achievable, I'd love to hear it. Thanks in advance.
You can use Jekyll's where filter coupled with a smart include:
{% assign book = site.data.book-data | where: 'title', include.title | first %}
<div class="book-meta">
<div class="book-thumbnail">
<img
class="post-thumbnail-lg"
src="{{ book.thumbnail | prepend: 'assets/images/' | relative_url }}"
alt="{{ book.title }}"
/>
</div>
<div class="book-details">
<ul class="book-meta-list">
<li class="book-meta-item"><p>{{ book.author }}</p></li>
<li class="book-meta-item"><p><em>{{ book.title }}</em></p></li>
<li class="book-meta-item"><p>{{ book.publisher }}</p></li>
<li class="book-meta-item"><p>{{ book.pub-date }}</p></li>
</ul>
</div>
</div>
Note that I also included thumbnail info in the data file..
Then just pass the title parameter to the include (in the layout for your book's page):
{% include books.html title = 'Everything Under' %}
If you'd like to render a "listing", then just loop through and render:
{% for book in site.data.book-data %}
{% include books.html title = book.title %}
{% endfor %}

Deletion by tab button doesn't work

Several DEVICE forms can be displayed on a page (Order), as tabs. When a user closes a tab and hits save, then renters that particular Order (ID), the user still sees his deleted tab. As a quick workaround, a checkbox was built into the html code but this is not desired.
Currently the code in my view.py looks like this.
def edit_order(request,id = None, order_id = None):
order = Order.objects.get(id=id)
'''some stuff'''
if request.method == 'POST':
formCustomer = CustomerModelForm(request.POST,instance=Customer.objects.get(order=order.id))
formInfo = InfoModelForm(request.POST,instance=Info.objects.get(order=order.id))
DBFormSet = modelformset_factory(DB, extra=1, can_delete=True, form=LUNModelForm)
formset = DBFormSet(request.POST or None, queryset=DB)
if formset.is_valid():
for i,frm in enumerate(formset.forms):
if frm.cleaned_data['id']:
if frm.is_valid():
if not frm.cleaned_data['capacityGB'] > 0:
frm.cleaned_data['id'].delete()
elif frm.cleaned_data['DELETE'] == True:
frm.cleaned_data['id'].delete()
#frm.save() or formset.save() ??
else:
dev = frm.cleaned_data['id']
dev.capacity = frm.cleaned_data['capacity']
dev.save()
I suspected the matter that the tab was not remaining closed was an issue with "can_delete", but it doesn't seem to make a difference when I added this. Then I read that the issue could be related to the formset.save, which also didn't resolve anything. Below the html code:
html:
<ul class="nav nav-tabs" id="tab4Headers">
{% for form in formsetDEVICE.forms %}
{% if forloop.first %}
{% if form.errors %}
<li class="active">DEVICE <i class="icon-warning-sign"></i> </li> <!-- section 4.1 -->
{% else %}
<li class="active">DEVICE</li> <!-- section 4.1 -->
{% endif %}
{% else %}
{% if form.errors %}
<li><button class="close" type="button" id="close-tab4_{{forloop.counter}}">×</button>DEVICE <i class="icon-warning-sign"></i> </i></li> <!-- section 4.2 ... 4.n -->
<!--{% if formsetDEVICE.can_delete %}
<li>{{ form.DELETE }}</li>
{% endif %}-->
{% else %}
<li><button class="close" type="button" id="close-tab4_{{forloop.counter}}">×</button>DEVICE</li> <!-- section 4.2 ... 4.n -->
<!--{% if formsetDEVICE.can_delete %}
<li>{{ form.DELETE }}</li>
{% endif %}-->
{% endif %}
{% endif %}
{% endfor %}
</ul>
Since it is not clear how to delete the tab via closing the tab (and then hit the save button), the current work around is simply to insert a section on the tab with a checkbox included, as so:
{# --- delete item --- #}
{% if form.instance.pk %}
{# render row for DELETE-flag only for forms with existing instance #}
<tr>
<td colspan="2">
</td>
<td colspan="2">
edit Action required: <br/><br/>
{{form.DELETE|safe}} delete this DEVICE from the Order.
</td>
</tr>
{% endif %}
{# --- END delete item --- #}
The current workaround works, but this is not the desired functionality. I've tried some of the suggestions as seen here, but to no avail. I think the problem is more related to the link between the html and the view.py (so something to do with frm.cleaned_data['DELETE'] though I could be wrong.
EDIT:
I suspect to get around this, js code and/or css needs to be inserted.
I was having the same problem with inlineformset_factory. Reading the base Django classes, i found the problem seems to be in BaseFormSet class (or some like that), the _should_delete_form() method looks for the forms DELETE value in cleaned_data, but using debugging i found that the DELETE value doesn't exist in cleaned_data, neither the DELETE field exists by the time cleaned_data is populated.
I think this could be because the DELETE field is dynamically created by FormSet Classes, but cleaned_data is populated by the Form class before the DELETE field is created (somewhere on forms init? maybe) so as this field doesn't exists, cleaned_data DELETE value isn't populated.
Somewhere in the base FormSet classes, the dynamically created DELETE field value have to be included in cleaned_data, BUT i found a quick and temporary solution to this, Add the DELETE field to the form class:
class RutinaForm(ModelForm):
DELETE = forms.BooleanField(required=False, widget=forms.CheckboxInput())
class Meta:
model = Rutina
fields = '__all__'
exclude = ('usuario',)
widgets = { .........}
This way the DELETE field exists so its value gets cleaned and added to cleaned_data.
This can be seen like a "machetazo", but it works! at least temporary. I will continue reading the base code and look if it is a bug, or what is happening.
Note: Sorry for my english, and i'm not an expert so PLEASE give me your comments.
This is my view if you need it, or if you can find what is wrong:
rutinaFormSet = inlineformset_factory(Usuario, Rutina, form=RutinaForm, can_delete=True, extra=1)
if request.method == 'POST':
formSet = rutinaFormSet(request.POST, instance=usuario)
if formSet.is_valid():
formSet.save()
else:
formSet = rutinaFormSet(instance=usuario)

How to add new posts like page in Jekyll?

I am setting up a GitHub page which uses Jekyll. I know how to create a new post, new page. I wanted a new "posts" like the page, wherein I can add posts which I want to. So there will be a posts page (by default) and there will be some other page say blog, both of which shows some posts in the appropriate category.
You can create a page which lists all posts which have a certain category or tag.
Example code from the link:
---
layout: page
---
{% for post in site.categories[page.category] %}
<a href="{{ post.url | absolute_url }}">
{{ post.title }}
</a>
{% endfor %}
If the .md files you are talking about aren't posts, you can use Collections.
Here's example code from the link tailored to your xyz example - basically, you define your collection in the config file:
collections:
- xyz
Then, you create .md files in an _xyz folder, and you can display a list of them like this:
{% for item in site.xyz %}
<h2>{{ item.title }}</h2>
<p>{{ item.description }}</p>
<p><a href = "{{ item.url }}" >{{ item.title }}</a></p>
{% endfor %}

Content types of my images doesn't display

Why is it the images will not display if I'm going to loop them like this?
{% for item in content.field_room_gallery_pictures['#items'].getValue() %}
<div class="col-xs-6 col-md-4 image-item">
{{item.value}}
</div>
{% endfor %}
And when I fetched the data if there is or not using kint.. it will display an array with the value of 3 using this code..So it means in my field_room_gallery_pictures there is an array of data.
{{kint(content.field_room_gallery_pictures['#items'].getValue())}}
have your tried this:
{% for i in 0..content.field_room_gallery_pictures|length %}
{%if content.field_room_gallery_pictures[i]['#item'].entity.uri.value != "" and content.field_room_gallery_pictures[i]['#item'].entity.uri.value is not empty %}
<div>
{{ content.field_room_gallery_pictures[i]}}
</div>
{%endif%}
{%endfor%}
works fine for me.

Jekyll Pagination Path Doesn't Include Page Number

I am attempting to create pagination in Jekyll under the path '/notes/'.
In my _config.yml, I have:
paginate: 2
paginate_path: "/notes/:num/"
In my /notes/index.html, I have:
<div class="pagination">
{% if paginator.previous_page %}
Previous
{% else %}
<span class="previous section link">Previous</span>
{% endif %}
<span class="page_number section">{{ paginator.page }} / {{ paginator.total_pages }}</span>
{% if paginator.next_page %}
Next
{% else %}
<span class="next section link">Next</span>
{% endif %}
</div>
When I load http://localhost:4000/notes, I see that the 'Previous' link is not linking to /notes/2, but instead it simply links to /notes/, the page that I am already on. Additionally, when looking in the generated _site folder, I see that /notes/2 has not been created, despite having more than two posts created.
So, I suppose my question is, how can I fix this and get jekyll to paginate properly?

Resources