Asynchronous JavaScript and XML (AJAX)
Understanding AJAX
AJAX stands for Asynchronous JavaScript and XML, which allows JavaScript to communicate asynchronously with the server using XML or JSON formats.
In synchronous communication, the client must wait for a server response before sending another request. Asynchronous communication allows multiple requests to be sent without waiting for previous responses.
Benefits include:
- Partial page updates without full reloads
- Dynamic content loading via JavaScript
jQuery Implementation of AJAX
$.ajax({
url: '',
type: 'POST',
data: {'username': $(this).val()},
success: function(data) {
const result = JSON.parse(data);
if (result['flag']) {
$('p>span').removeClass('hide');
}
}
});
Server-side access:
request.POST or request.GET
Sending JSON Data with jQuery AJAX
$('#d1').click(function() {
$.ajax({
url: '',
type: 'post',
data: JSON.stringify({'name': 'jason', 'age': '18'}),
contentType: 'application/json',
success: function(data) {
$('#i3').val(data);
}
});
});
Server-side access:
request.body # Returns bytes
File Upload Using AJAX
Key considerations:
- Use
new FormData() - Access file input via
$('#i1')[0].files[0] - Set
processDataandcontentTypetofalse - Retrieve files from
request.FILES - Regular key-value pairs can also be included in FormData
$("#btn").click(function() {
var formdata = new FormData();
formdata.append('name', $("#name").val());
formdata.append('myfile', $("#myfile")[0].files[0]);
$.ajax({
url: '/index/',
type: 'post',
processData: false,
contentType: false,
data: formdata,
success: function(data) {
alert(data);
}
});
});
Backend handling:
def plus(request):
if request.method == 'POST':
print(request.FILES)
file_obj = request.FILES.get('myfile')
with open(file_obj.name, 'wb') as f:
for chunk in file_obj:
f.write(chunk)
return HttpResponse('ok')
return render(request, 'index.html')
Custom Pagination Class
Implementation of a custom pagination utility:
class Pagination(object):
def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
try:
current_page = int(current_page)
except Exception as e:
current_page = 1
if current_page < 1:
current_page = 1
self.current_page = current_page
self.all_count = all_count
self.per_page_num = per_page_num
self.all_pager = int((all_count + per_page_num - 1) / per_page_num)
self.pager_count = pager_count
self.pager_count_half = int((pager_count - 1) / 2)
@property
def start(self):
return (self.current_page - 1) * self.per_page_num
@property
def end(self):
return self.current_page * self.per_page_num
def page_html(self):
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
else:
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1
else:
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_end = self.all_pager + 1
pager_start = self.all_pager - self.pager_count + 1
else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1
page_html_list = []
page_html_list.append('''
<nav aria-label='Page navigation'>
<ul class='pagination'>
''')
first_page = '<li><a href="?page=%s">First Page</a></li>' % (1)
page_html_list.append(first_page)
if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="#">Pre Page</a></li>'
else:
prev_page = '<li><a href="?page=%s">Pre Page</a></li>' % (self.current_page - 1,)
page_html_list.append(prev_page)
for i in range(pager_start, pager_end):
if i == self.current_page:
temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
else:
temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
page_html_list.append(temp)
if self.current_page >= self.all_pager:
next_page = '<li class="disabled"><a href="#">Next Page</a></li>'
else:
next_page = '<li><a href="?page=%s">Next Page</a></li>' % (self.current_page + 1,)
page_html_list.append(next_page)
last_page = '<li><a href="?page=%s">Last Page</a></li>' % (self.all_pager,)
page_html_list.append(last_page)
page_html_list.append('''
</nav>
</ul>
''')
return ''.join(page_html_list)
Usage in backend:
def publisher_list(request):
current_page = int(request.GET.get('page'))
total_count = models.Publisher.objects.count()
page_obj = Pagination(current_page, total_count, request.path_info)
data = models.Publisher.objects.all()[page_obj.start:page_obj.end]
page_html = page_obj.page_html()
return render(request, "publisher_list.html", {"publisher_list": data, "page_html": page_html})
Frontend rendering:
{{ page_html|safe }}