How to refresh a table in template of Django - javascript

I am currently obtaining an object from my views and displaying it in the template in form of a table. Currently I am struck at the part that we need to refresh the table/div, without refreshing the page.
In my views.py
def foo(request):
testruns......
render_to_response('pages/bar.html', locals(), context_instance=RequestContext(request))
My bar.html (template)
<div id = "roman">
{% for trun in testruns %}
<tr>
<td>{{ trun.testprofile }}</td>
<td>{{ trun.time }}</td>
<td>{{ trun.testresult }}</td>
<td>{{ trun.state }}</td>
</tr>
{% endfor %}
</div>
There are two approaches which are supposed to work:
Using dajaxice
Using [Jquery]
$.ajax({
url: '{% url myview %}',
success: function(data) {
$('#the-div-that-should-be-refreshed').html(data);
}
});
I would like to know which approach is more suitable to my case. Using Approach 2, would the table auto refresh, and how do we set the time to refresh ?

Both acceptable but disadvantages of the second approach(pulling table from django as html ):
Carried data over network is much bigger
If u use something javascript based components in your table (maybe
dojo based buttons etc.) they may cause some problems. I had a
smilar issue in dojo and i found the solution in make dojo reparse
the applied html. But life could not be easy everytime so first
approach is better.

If this is only place where you need an auto-refresh, your approach 2 should work along with setting a timer to do the auto-refresh. You can use the setInterval function for the purpose:
// Refresh the Table every 5 seconds
setInterval(function(){
$.ajax({
url: '{% url myview %}',
success: function(data) {
$('#the-div-that-should-be-refreshed').html(data);
}
});
}, 5000)
But if you are planning on developing a responsive webpage, where the whole UI needs to be kept updated, then I would suggest to use a full fledged framework like ember.js

Related

Django Python - Javascript Dynamic Table sorting rows

I have never done any javascript but I saw that this is what I am looking for to display a dynamic table one of my html template.
I have read that there should be something using JQuery but not much more.
So I am looking exactly for an example of dynamic table able to sort rows following which column is selected, written in javascript, displayed in an HTML template, using:
- as columns: the fields of a MySQL table (see example below).
- as rows: the entries contained in the same table
And all of this has to use Django (I don't know if the javascript file either has to be separated from the HTML template or has to be in the HTML template)
Example MySQL table:
CREATE TABLE PDB(
id_PDB_chain CHAR(5) NOT NULL PRIMARY KEY,
id_PDB CHAR(4) NOT NULL,
chaine VARCHAR(10) NOT NULL,
header VARCHAR(255) NOT NULL,
sequence_Proteine TEXT NOT NULL,
start_seq INT NOT NULL,
taille_Proteine INT NOT NULL,
resolution_PDB FLOAT NOT NULL,
meth_Res VARCHAR(10) NOT NULL,
FOREIGN KEY (meth_Res)
REFERENCES methodes_res(meth_Res)
ON DELETE CASCADE
);
Corresponding class in the "models.py" file:
from __future__ import unicode_literals
from django.db import models
class Pdb(models.Model):
id_pdb_chain = models.CharField(db_column='id_PDB_chain', primary_key=True, max_length=5) # Field name made lowercase.
id_pdb = models.CharField(db_column='id_PDB', max_length=4) # Field name made lowercase.
chaine = models.CharField(max_length=10)
header = models.CharField(max_length=255)
sequence_proteine = models.TextField(db_column='sequence_Proteine') # Field name made lowercase.
start_seq = models.IntegerField()
taille_proteine = models.IntegerField(db_column='taille_Proteine') # Field name made lowercase.
resolution_pdb = models.FloatField(db_column='resolution_PDB') # Field name made lowercase.
meth_res = models.ForeignKey('MethodesRes', models.DO_NOTHING, db_column='meth_Res') # Field name made lowercase.
def __unicode__(self):
return self.id_pdb
class Meta:
managed = False
db_table = 'PDB'
In case you need any other informations just ask in comments and I will edit this post with the informations.
In your views.py create a view under whatever name you'd like. Create a list and set it to whatever data you want from your specific model. now go to your template. With that list populated by your specific data you have chosen from the database, use an If statement to check to see if there is anything residing in that list. If there is data there then you can use a For loop like so:
{% for model_name in list_name %}
model_name.model_data etc # Mark it up with relevant html table code, though divs are more preferred
You can mark up the data as needed to display a table, though divs would be more compliant and nicer than tables. This is just a basic example. On the Else statement if no data exists in the list ahead of time, you can simply output that no data exists. Take a look here https://docs.djangoproject.com/en/1.10/intro/tutorial01/
They walk you through building a polling app, where it is relevant to you is the index.html template they build pulling the question data from the database and displaying an unordered list of the questions on the home page as links to vote on. Simply follow this tutorial and look at how they implement the models.py and views.py along with the template and then change the markup from am unordered list to whatever suits your needs.
I found a solution that worked for me and it was really simple in fact:
first you have to download jquery and jquery.tablesorter. Here is the official website where you can download everything and where everything is explained : http://tablesorter.com/docs/
Then, as I work with Django my HTML templates are in a "myapp/templates" directory and my CSS and Javascript files are in a "myapp/static/myapp/" directory.
Here is the template I used:
{% load static %}
<head>
<link rel="stylesheet" type="text/css" href="{% static 'myapp/style.css' %}" />
<script type="text/javascript" src="{% static 'myapp/jquery-3.2.0.min.js' %}">
</script>
<script type="text/javascript" src="{% static 'myapp/jquery.tablesorter.min.js' %}">
</script>
<script type="text/javascript">
$(document).ready(function()
{
$("#pdbtable").tablesorter();
}
);
</script>
</head>
{% if protdb %}
<table id="pdbtable" align="center" border="3" width="100%">
<thead>
<tr>
<th>PDB Id</th>
<th>Chain</th>
<th>Header</th>
<th>Size</th>
<th>Resol.</th>
<th>Method Res.</th>
</tr>
</thead>
<tbody>
{% for i in protdb %}
<tr>
<td>{{ i.id_pdb }}</td>
<td>{{ i.chaine }}</td>
<td>{{ i.header }}</td>
<td>{{ i.taille_proteine }}</td>
<td>{{ i.resolution_pdb }}</td>
<td>{{ i.meth_res }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No PDBs are available.</p>
{% endif %}
And here is my corresponding view:
def pdbinfo(request):
protdb = Pdb.objects.order_by('id_pdb_chain')\
[:len(Pdb.objects.order_by('id_pdb_chain'))]
context = {
'protdb': protdb
}
return render(request, 'pdbapp/pdbinfo.html', context)
As you maybe know, since you are using Django, your template has to receive all informations from a view in views.py and the table of your database (in my case I use MySQL) have to be filled with entries.
This code is working, take some inspiration from it.
One other content that helped me and that gives more details is a youtube video, check the link here: https://www.youtube.com/watch?v=-wAWfPVXlME&t=334s
I hope it will help!

Load data on scroll down in Django

I am currently working on a web application to feature the interface in django and how the content loads.
In my database, potentially thousands of these entries, and I want to make sure that only has to load a given number at a time to reduce stress on the servers etc.
lets say I have 5000 records and initially Load a given number of objects.
then load the next set of records once the I reaches the record at the bottom of the screen.
views.html:
def list(request):
list_data = Container.objects.all()
return render(request,
'list.html',
{'list_data': list_data,})
list.html:
{
% block content %}
<table border="1" >
<tr>
<th>list name</th>
<th>received</th>
<th>student name</th>
</tr>
{% for list_item in list_data %}
<tr>
<td>{{ list_item.serial_number}}</td>
<td>{{ list_item.received}}</td>
<td>{{list_item.studentss}}</td>
</tr>
</table>
{% endblock %}
I have this table in my view which contains large number of data.How do I change these so that I can use scroll down in Django??
Note: I don't want to use pagination to load the data.
I believe this combines the django pagination, but utilizes it in an ajax function to add to the existing page without a reload:
http://django-endless-pagination.readthedocs.org/en/latest/twitter_pagination.html
For Django 1.8 and above use:
Django EL(Endless) Pagination:
This app django-el-pagination created from
django-endless-pagination==2.0.
https://github.com/shtalinberg/django-el-pagination
Django Endless Pagination says:
This project is abandoned.
Thanks to the community that supported django-endless-pagination over
time. I do not have time to properly maintain and develop this
application. From now on, please use one of the great forks like
https://github.com/shtalinberg/django-el-pagination

Datatable hide and show rows based on a button click event

So I have this datatable that is generated by php dynamically once. But once it's loaded, I don't want to reload the whole table since there's only a small javascript if statement that I am doing. When you press the button, I compare a data attribute that is on my tr. If it doesn't fit, I'd like to hide them, else, I'd like to show them. So here is what I tried so far.
HTML
<div style="margin: 30px 0;">
<button class="btn btn-primary" id="myClientButton">Voir mes clients seulements</button>
</div>
<table id="advancedSearchTable">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th>Subject</th>
<th>Date</th>
<th>Profile</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr data-user="{{ entity.user.id }}" class="values">
<td>{{ entity }}</td>
<td>{{ entity.mainphone }}</td>
<td>{{ entity.email }}</td>
<td>{{ entity.tagline }}</td>
<td>{{ entity.createdDate|date('d-m-Y') }}</td>
<td><span class="glyphicon glyphicon-eye-open"></span></td>
</tr>
{% endfor %}
</tbody>
</table>
The Loop is made in Symfony 2 (Using Twig Template, if you don't understand it it doesn't really matter) all you have to understand is that the attribute on "data-user" is created by PHP and that every entry of my database is going in this loop.
Then, in jQuery I have this:
<script>
$('#advancedSearchTable').DataTable(
{
"language": {
"url": "//cdn.datatables.net/plug- ins/9dcbecd42ad/i18n/French.json"
},
responsive: true
});
$('#myClientButton').on('click', function(){
if ($(this).hasClass('active')){
$(this).removeClass('active');
$('tr.values').show();
}
else{
$(this).addClass('active');
$('tr.values').each(function(){
if ($(this).attr('data-user') != 5){
$(this).hide();
}
});
}
});
</script>
It works very well. The only problem is that the DataTable then is not "replacing itself". So, for example, if it has 25 pages, it keeps 25 pages and when you press on the "next table page" button, it refreshes the "table page" and things are not hidden anymore. I searched alot but I couldn't find a way. I really don't want to use ajax for this, since it only need to be filled once with value and then it will only have to hide or show depending on the button being active or not... Is it even possible using this jQuery plugin ?
Thanks in advance.
Yes, it is indeed possible, but you will need a different approach. Hiding rows with jQuery and not through dataTables itself is generally a bad idea, since dataTables is not aware of changes made to the original <table> element in DOM. There is no "somewhere-in-code-another-script-has-hidden-a-row"-event dataTables can hook into. That is why dataTables seems to "forget" changes, it is simply not aware of those changes, and the dataTables internals stay untouched.
So use a custom filter instead. The following small piece of code does what you want - hiding all rows having a data-user attribute different than 5. It works across sorting and pagination. The last piece of code is an example of a reset-button.
$("#hide").click(function() {
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
return $(table.row(dataIndex).node()).attr('data-user') == 5;
}
);
table.draw();
});
$("#reset").click(function() {
$.fn.dataTable.ext.search.pop();
table.draw();
});
demo -> http://jsfiddle.net/d5hre2ux/
According to this https://datatables.net/examples/plug-ins/range_filtering.html it is possible to use data parameter to filter by any value shown on the table.
$("button").click(function() {
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
return data[3] != "63";
}
);
table.draw();
});

WTForms submitting form twice when multiple forms are in the same page

On my view I have a few different forms. In one you enter a first and last name to search for. If there are results, the page refreshes and a second form to pick a user is displayed as a table where clicking on a row submits the data from that row. For some reason, submitting the second form results in submitting two values for each field: one completely empty and one with the correct information.
I have some javascript that will be executed when a row in a table is clicked. It's supposed to fill out and submit a hidden form with the data from the table. The problem I'm running into is that when the form is submitted, two sets of values are submitted. request.form after the form is submitted contains the following:
ImmutableMultiDict([('csrf_token', u'1420171907##6ad5346730985191250a52e6432e924ef05c23ee'), ('last_name', u''), ('last_name', u'Smith'), ('first_name', u''), ('first_name', u'John')])
Here's the script:
$('table#theTable tr').click(function () {
var cells = this.getElementsByTagName('td');
$('#selectuser_last_name').val(cells[0].innerHTML);
$('#selectuser_first_name').val(cells[1].innerHTML);
document.selectuser.submit();
});
and here is the HTML to go along with it:
<table id="theTable">
<thead>
<tr>
<th>Last</th>
<th>First</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.last_name }}</td>
<td>{{ user.first_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<form id=selectUserForm action="/handle_users" method="post" name="selectuser">
{{ forms.selectuser.hidden_tag() }}
{{ forms.selectuser.last_name(id="selectuser_last_name") }}
{{ forms.selectuser.first_name(id="selectuser_first_name") }}
<input type="submit">Test</input>
</form>
I'm using Python and Flask to handle whatever is posted.
It seems you're actually submitting twice- once before there's anything in the form, and once after it's populated (the latter by the javascript, the former via the form submit mechanism).
If the user isn't really inputting anything into the form, but this is a simple call to the server any time a row is clicked. Skip the whole form, it's not helping here. Just pass a call to the server with the info you need- can be a simple ajax post:
$('table#theTable tr').click(function () {
var cells = this.getElementsByTagName('td');
$.ajax({
type : "POST",
url : "/handle_users",
async:true,
contentType : 'application/json;charset=UTF-8',
data: JSON.stringify({first_name:cells[0].innerHTML,last_name:cells[1].innerHTML}, null, '\t'),
success : function(data) {
// optional: do something when server-side processing is done
}
});
});
Then Grab your data on from flask using request.get_json() in the /handle_users route.

Django / jQuery - Button to update a value on each row of a table

I am just learning Django, so I am making an app that can keep track of books with a Boolean for whether I have read them or not as a learning project. The model is relatively self explanatory books have title and id and a boolean completed "field". I want to have a page that lists the books and has a button next to each book that will change the read status to True and update immediately using AJAX/jQuery (and eventually a similar unread button for mistakes). I am having trouble getting the button to work. Specifically I think I need to somehow assign some sort of id to each row so that jQuery knows which item it is working with.
Apologies for any obvious errors. I am new to web programming and I regret having to ask you all for help, but I have been trying to work out a solution myself for a few days now.
Here is the django template snippet:
{% for book in lib_dict.books %}
<tr>
<td>{{ book.title }}</td>
<td>{{ book.date_due }}</td>
<td id="book_completed_{{ book.id }}">{{ book.completed }}</td>
<td>
<button id="{{ book.id }}" data-bookid="{{ book.id }}" class="btn-mini btn-primary c" type="button">Complete</button>
</td>
</tr>
{% endfor %}
views.py:
def complete_book(request):
context = RequestContext(request)
book_id = None
if request.method == 'GET':
book_id = request.GET['book_id']
if book_id:
book = Book.objects.get(id=int(book_id))
if book:
book.completed = True
book.save()
return HttpResponse(book.completed)
jQuery code - I would imagine the error(s) are here
$('.btn-mini btn-primary c').click(function(){
var bookid;
bookid = $(this).attr("data-bookid");
$.get('/libco/complete_book/', {book_id: bookid}, function(data){
var bookstring = '#book_completed_' + bookid;
$(bookstring).html(data); \\trying to update the completed table cell
$('#bookid').hide(); \\trying to hide the button
});
});
Please note, all of the connectivity works fine. If I just make this button for a single row with a dedicated id, and use the appropriate #-tag in the first line of the jQuery it works, but I am having trouble with the generalization. Maybe the "." thing isn't the way to get the class in the first line?
Also, I am very much trying to teach myself, so if there are any good resources for this kind of thing please let me know. I started working on the official jQuery tutorial, but I looked through it quickly and nothing seemed too related to this.
Thanks you all!
Change this:
$('.btn-mini btn-primary c')
to:
$('.btn-mini.btn-primary.c')

Categories