Refreshing a specific div every few seconds in django using javascript - javascript

I am trying to refresh the content of a table every few seconds in my HTML page using javascript. I keep getting 500 error when it tries to refresh the div, internal server error. Could someone enlighten the reason this is not working? I have used this: Refresh div using JQuery in Django while using the template system
as a reference to what I was doing. The page loads perfectly the first time just fails to refresh.
Here is my code:
urls.py
url(r'^specialScoreboard/$', views.specialScoreboard.as_view(), name='specialScoreboard'),
url(r'^specialScoreboardDiv/$', views.specialScoreboardDiv , name='specialScoreboardDiv'),
views.py
class specialScoreboard(generic.ListView):
template_name = 'CTF/specialScoreboard.html'
context_object_name = 'teams'
#method_decorator(login_required)
#method_decorator(never_ever_cache)
def dispatch(self, request, *args, **kwargs):
if getAnyActiveGame and request.user.is_staff:
return super(specialScoreboard, self).dispatch(request, *args, **kwargs)
else:
return HttpResponseRedirect(reverse('CTF:no_active_game'))
def get_queryset(self):
"""
ordering teams by score
"""
game = getAnyActiveGame()
teams = get_teams_from_game(game)
return sorted(teams, key=lambda a: a.get_score(game), reverse=True)
def specialScoreboardDiv():
game = getAnyActiveGame()
teams = get_teams_from_game(game)
sortedList = sorted(teams, key=lambda a: a.get_score(game), reverse=True)
return render_to_response('CTF/specialscoreboardDiv.html' , {'sortedList' :sortedList})
scoreboardRefresh.js + scoreboardDiv.html
<script>
var scoreboardURL = '{% url '
CTF: specialScoreboardDiv ' %}';
function refresh() {
$.ajax({
url: scoreboardURL,
success: function(data) {
$('#scoreboardDiv').html(data);
}
});
};
$(document).ready(function($) {
refresh();
setInterval("refresh()", 3000);
})
</script>
<div class="panel panel-info">
<div class="panel-heading">Scoreboard</div>
<div class="panel-body">
<div class="table-striped">
<table id="scoreboardDiv" class="table table-hover">
<thead>
<tr>
<th>#</th>
<th>Team Name</th>
<th>Score</th>
</tr>
</thead>
<tbody>
{% for team in teams %}
<tr>
<td>{{forloop.counter}}</td>
<td>{{team.name}}</td>
<td>{{team|getScoreTeam}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
I can't seem to be able to format the error, here is a picture of it: http://i.imgur.com/Yc11juA.png
http://i.imgur.com/QluqZyc.png
http://imgur.com/QluqZyc

Your django view takes no arguments, but usually django tries to pass request param into it. From the error in the screenshot you provided in comments, looks likŠµ this is your problem.
I think you error will be fixed by making your view function take this argument:
def specialScoreboardDiv(request):
game = getAnyActiveGame()
...

Related

Update DataTable with JsonResponse from Django not working properly

I have a Django application and a page where data is written to a table that I am styling using DataTables. I have a very simple problem that has proven remarkably complicated to figure out. I have a dropdown filter where users can select an option, click filter, and then an ajax request updates the html of the table without reloading the page. Problem is, this does not update the DataTable.
My html:
<table class="table" id="results-table">
<thead>
<tr>
<th scope="col">COL 1</th>
<th scope="col">COL 2</th>
<th scope="col">COL 3</th>
<th scope="col">COL 4</th>
<th scope="col">COL 5</th>
</tr>
</thead>
<tbody class="table_body">
{% include 'results/results_table.html' %}
</tbody>
</table>
results_table.html:
{% for result in result_set %}
<tr class="result-row">
<td>{{ result.col1 }}</td>
<td>{{ result.col2 }}</td>
<td>{{ result.col3 }}</td>
<td>{{ result.col4 }}</td>
<td>{{ result.col5 }}</td>
</tr>
{% endfor %}
javascript:
function filter_results() {
var IDs = [];
var IDSet = $('.id-select');
for (var i = 0; i < IDSet.length; i++) {
var ID = getID($(IDSet[i]));
IDs.push(ID);
}
// var data = [];
// data = $.ajax({
// url:"filter_results/" + IDs + "/",
// dataType: "json",
// async: false,
// cache: false,
// data: {},
// success: function(response) {
// $('#results-table').html(response);
// // console.log(response.length);
// // console.log(typeof response);
// //
// }
// }).responseJSON;
var dataTable = $('#results-table').DataTable();
dataTable.clear();
$('.table_body').html('').load("filter_results/" + IDs + "/", function() {
alert("Done");
});
dataTable.draw();
}
And views:
def filter_results(request, ids):
ids = [int(id) for id in ids.split(',')]
account_set = Account.objects.filter(id__in=ids)
form = ResultsFilterForm()
result_set = Result.objects.filter(account__in=account_set)
context = {
'form': form,
'result_set': result_set
}
return render(request, 'results/results_table.html', context)
What is happening is that the Ajax is correctly updating what I see on the HTML page, but it is not updating the actual data table. So I can filter for a particular ID, for instance, which has 2 results and this will work and show me the two results on the HTML page without reloading it. However, the DataTable still contains the rest of the results so there is still like a "next" page which makes no sense when there are only 2 results.
I also tried changing the view to return a JSON response with the code that is commented out of the JS and when I did that I got "Warning: DataTable encountered unexpected parameter '0' at row 0 column 0" even though the data coming from Django was the correct data in JSON form.
Really stuck here, appreciate the help.
I figured out a way to make it work. Though maybe not the "best" way to do this, it is simple so I hope this helps someone else. Change JavaScript as follows:
function filter_results() {
$('#results-table').DataTable().destroy();
var IDs = [];
var IDSet = $('.id-select');
for (var i = 0; i < IDSet.length; i++) {
var ID = getID($(IDSet[i]));
IDs.push(ID);
}
$('.table_body').html('').load("filter_results/" + IDs + "/", function() {
$('#results-table').DataTable();
});
}
That was it. All I needed to do was destroy the old DataTable at the beginning of the filter_results function and then re-create it. Note however that the recreation is the function to execute after the call to .load(). If you don't write it like this you will have an issue with JS recreating the DataTable before the the html is finished loading, which is a problem I encountered. Nesting that function inside the .load() call is an easy workaround though.
I know there is probably a better way to do this, one that involves updating rather than destroying and recreating the DataTable. If somebody knows of it feel free to post it as an answer but for now this workaround is good for me!

Ajax paging is duplicating _layout page while using pagination to replace page content

I am using x.PagedList to use pagination in my ASP.NET MVC page. The only problem I have with the plugin is , it used a page refresh when I navigate between pages.
To avoid that I am using jQuery calls to replace page contents as explained in this article.
My View and javascript looks like this.
<div id="circuitsContent">
<table class="table">
<tr>
--Header
</tr>
#foreach (var item in Model)
{
<tr>
--Loop through and create content
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
#Html.ActionLink("Details", "Details", new { id = item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}
</table>
</div>
<div id="circuitContentPager">
#Html.PagedListPager((IPagedList)Model, page => Url.Action("Circuits", new { page }))
</div>
#section scripts
{
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$(document).on("click", "#circuitContentPager a[href]", function () {
$.ajax({
url: $(this).attr("href"),
type: 'GET',
cache: false,
success: function (result) {
$('#circuitsContent').html(result);
}
});
return false;
});
});
</script>
And this is my controller code:
public ActionResult Circuits(int? page)
{
var pageNumber = page ?? 1;
var circuits = _repo.GetAllCircuits().OrderBy(circ=>circ.ID).ToList();
var pagedCircuits = circuits.ToPagedList(pageNumber, 25);
return View(pagedCircuits);
}
What am I missing here?
Your ajax call returns the html from Circuits() method which is the same view you have used to render the page initially, which includes all the initial html, but you only replacing part of of the existing page, so elements such as the paging buttons generated by the #Html.PagedListPager() method are going to be repeated. Your also generating invalid html because of duplicate id attributes (you will have multiple <div id="circuitsContent"> elements
There are 2 ways you could solve this.
Create a separate controller method that returns a partial view of just the <table> and call that method, however you would need to extract the value of the page number for the href attribute of you pager buttons to pass that as well.
Using your current Circuits() method, test if the request is ajax, and if so, return a partial view of just the <table>.
public ActionResult Circuits(int? page)
{
var pageNumber = page ?? 1;
var circuits = _repo.GetAllCircuits().OrderBy(circ=>circ.ID);
var pagedCircuits = circuits.ToPagedList(pageNumber, 25);
if (Request.IsAjaxRequest)
{
return PartialView("_Circuits", pagedCircuits);
}
return View(pagedCircuits);
}
Note: Do not use .ToList() in your query. That is defeating the whole purpose of using server side paging because .ToList() immediately downloads all the records fro the database.
Where _Circuits.cshtml would be
#model IEnumerable<yourModel>
<table class="table">
<thead>
<tr>
// <th> elements
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
.... // Loop through and create content
</tr>
}
</tbody>
</table>
Note that your header elements should be in a <thead> element and the records in a <tbody> element.

Django website not checking the links correctly

I have a django website that contains a table with many servers details.
In one of the columns in the table there is "ILO" IP of a server.
I wanted the website to check if the "ILO" IP works in http request, and if it does, then it should show the link and if not, shows a text instead.
Therefore, in the result, will be servers that has http link to ILO IP and some without.
Under my main class in the views I created a function called "checkUrlAvailable" which I try to use in my index.html and check with if condition if I get true or false..
for some reason I get the errorr-
Could not parse the remainder: '(server.IP)' from 'checkUrlAvailable(server.IP)'
Does anyone know why?
index.html-
<tr>
<th><center> #</center></th>
<th width="100%"><center> Server Name </center></th>
<th><center> Owner </center></th>
<th><center> Project </center></th>
<th width="100%"><center> Description </center></th>
<th width="100%"><center> IP Address </center></th>
<th width="100%"><center> ILO </center></th>
<th><center> Rack </center></th>
<th><center> Status </center></th>
<th><center> Actions {{ response }} </center></th>
</tr>
</thead>
<tbody>
{% for server in posts %}
<tr>
<div class ="server">
<td></td>
<td style='white-space: nowrap'><center>{{ server.ServerName }}</center></td>
<td width="100%"><center>{{ server.Owner }}</center></td>
<td style='white-space: nowrap'><center>{{ server.Project }}</center></td>
<td style='white-space: nowrap'><center>{{ server.Description }}</center></td>
<td width="100%"><center>{{ server.IP }}</center></td>
<td style='white-space: nowrap'><center>
{% if checkUrlAvailable(server.ILO) is True %}
http://{{ server.ServerName }}.ilo.lab.radcom.co.il
{% else %}
http://{{ server.ServerName }}.ilo.lab.radcom.co.il
{% endif %}
<td width="100%"><center>{{ server.Rack }}</center></td>
<td width="100%"><h4><span class="badge badge-success">Online</span></h4></td></center>
views.py -
class HomeView(TemplateView):
template_name = 'serverlist.html'
def checkUrlAvailable(url):
resp = requests.head(url)
if resp.status_code == 200:
return True
else:
return False
def get(self, request):
form = HomeForm()
query = request.GET.get("q")
posts = serverlist.objects.all()
forms = {}
if query:
posts = serverlist.objects.filter(Q(ServerName__icontains=query) | Q(Owner__icontains=query) | Q(Project__icontains=query) | Q(Description__icontains=query) | Q(IP__icontains=query) | Q(ILO__icontains=query) | Q(Rack__icontains=query))
else:
posts = serverlist.objects.all()
for post in posts:
forms[post.id] = HomeForm(instance=post)
args = {'form' : form,'forms': forms, 'posts' : posts}
return render(request, self.template_name,args)
def post(self,request):
form = HomeForm(request.POST)
posts = serverlist.objects.all()
forms = {}
if form.is_valid(): # Checks if validation of the forms passed
post = form.save(commit=False)
post.save()
messages.success(request,'{0} has been added successfully!'.format(post.ServerName))
return redirect('serverlist')
messages.error(request,'Servername is required, please refresh the page and try again.')
for post in posts:
forms[post.id] = HomeForm(instance=post)
args = {'form' : form, 'forms': forms, 'posts' : posts}
return render(request, self.template_name,args)
You cannot call function inside django template. You need to define custom template tag or you can move checkUrlAvailable inside serverlist model:
class serverlist(models.Model):
...
def checkUrlAvailable(self):
resp = requests.head(self.ILO)
if resp.status_code == 200:
return True
else:
return False
and use it in template like this:
{% if server.checkUrlAvailable %}

django: How to set date and time to server from client

I try to semplify my situation:
I have two PC, PC1 ("server") is not on the web, instead the PC2 ("client") can surf on the web (they communicate between each other).
Into PC1 I have my Django project, DB etc.. while with PC2 I can access via browser to my project an so on.
I would like to reach this goal:
PC1 take the date and time from PC 2 automatically and in PC 1 every actions refers to time and date of PC2.
| PC1 (server-side) | <--datetime--- | PC2 (client-side) |<----- datetime from web
Actually I can take the client datetime with some js:
datetime.js
$(document).ready(function(){
var myVar=setInterval(function(){myTimer()},1000);
function myTimer() {
var myDate = new Date();
var strDate = myDate.getFullYear()+ "-" +(myDate.getMonth()+1)+ "-" +myDate.getDate();
var strTime = myDate.getHours()+ ":" + myDate.getMinutes() +":" + myDate.getSeconds();
document.getElementById("data").innerHTML = myDate.toLocaleString();
}
})
models.py
from django.db import models
class ProvaTime(models.Model):
somewords = models.CharField(max_length=30)
myauthor = models.ForeignKey('auth.User', null=True, blank=False)
created_date = models.DateTimeField() # how tell it to pick js timedate?
def save(self, *args, **kwargs):
super(ProvaTime, self).save(*args, **kwargs)
forms.py
from django import forms
from .models import ProvaTime
class ProvaTimeForm(forms.ModelForm):
class Meta:
model = ProvaTime
fields = ('somewords',)
views.py
def testime(request):
elements =ProvaTime.objects.filter().order_by('-created_date')
if request.method == 'POST':
form = ProvaTimeForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.author = request.user
obj.save()
else:
form = ProvaTimeForm()
return render(request, 'provapp/testime.html', {'form': form, 'elements': elements})
def myviewtomodel(request): # how to do?
provapp/testime.html
<form action="/testime/" method="post">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" value="LIST" />
</form>
<br />
<br />
<div class="table-responsive">
<table class="table table-bordered">
<tr class="info">
<td width="15%" align="center">SOMETHING WORDS</td>
<td width="15%" align="center"> CREATION DATETIME </td>
<td width="15%" align="center"> AUTHOR </td>
<td>
</td>
{% for stuff in elements %}
<div class="stuff">
<tr>
<td>{{stuff.somewords}}</td>
<td>{{stuff.created_date}}</td>
<td>{{stuff.myauthor}}</td>
</div>
{% endfor %}
</table>
</div>
How can I send JS datetime to models.py?
You should pass the javascript date to your models explicitly.
model.created_date = date_from_javascript
Since you have set the default value for created_date as timezone.now it will use the server's timezone when nothing is passed to it.
ex.
$.ajax({
url: '/myview/',
data: {'javascript_date' : javascript_date},
method: 'post',
....
});
in your django view:
def MyView(request):
javascript_date = request.POST['javascript_date']
m = MyModel(created_at=javascript_date)
m.save()
I would recommend to not save client time directly in the database. Because while there is multiple clients with different timezone, then one client will see wrong time as that was created in separate timezone. I will suggest you to use session to save the offset value (Or database)and use it for displaying data.
Now lets make an ajax request in home page or another page which will send the offset data to the server from browser.
$(document).ready(function(){
var now = new Date()
var value = now.getTimezoneOffset()
$.ajax({
url: "your-url",
type: "post", // or "get"
data: value,
success: function(data) {
console.log(data);
}});
});
add an extra field to model to save that offset. And a property method which will later calculate user's local time.
class ProvaTime(models.Model):
....
tz_offset = models.DecimalField(default=Decimal('0.0'),max_digits=3, decimal_places=1)
#property
def get_local_time(self):
return create_time - datetime.timedelta(tz_offset)
and ajax the view
import json
def post(request):
if request.POST():
data = {}
try:
get_value= request.body
prova_times = ProvaTime.objects.filter(myauthor=request.user)
if prova_times.exists():
for prova_time in prova_times:
prova_time.tz_offset = get_value
prova_time.save()
data['success'] = 'Success'
return HttpResponse(json.dumps(data), content_type="application/json")
except Exception as e:
data['error'] = e
return HttpResponse(json.dumps(data), content_type="application/json")
Now displaying the data:
def myviewtomodel(request):
context = dict()
context['elements'] = ProvaTime.objects.all()
return render(request, 'myapp/index.html', context,
content_type="application/xhtml+xml")
Showing time in template(using get_local_time).
<div class="table-responsive">
<table class="table table-bordered">
<tr class="info">
<td width="15%" align="center">SOMETHING WORDS</td>
<td width="15%" align="center"> CREATION DATETIME </td>
<td width="15%" align="center"> AUTHOR </td>
<td>
</td>
{% for stuff in elements %}
<div class="stuff">
<tr>
<td>{{stuff.somewords}}</td>
<td>{{stuff.get_local_time}}</td>
<td>{{stuff.myauthor}}</td>
</div>
{% endfor %}
</table>
</div>

Retrieving the id from Model to Controller in Angular JS

i have a table which is having the data retrieved from an api call from my memberController which is displayed inside ng-repeat and its working fine.
I need each Business Name of the member list to link to a separate page(edit_form.html) and display the id value, so that i can pass this along with the api call to get only this particular member detail. So i have added ng-init in my edit form page which calls the function test_funct when the page loads and retrieve each persons id there. unfortunately i am unable to retrieve the id value inside the function.
HTML Template
<div class="page" data-ng-controller="memberController">
<table>
<thead >
<tr>
<th>Business Name</th>
<th>Contact Name</th>
<th>Trade Balance</th>
<th>Cash Balance</th>
<th>Telephone</th>
<th>Account Number </th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="member in details | filter:search">
<td>{{member.businessname}}</td>
<td>{{member.person}}</td>
<td>{{member.balance_trade}}</td>
<td>{{member.balance_cash}}</td>
<td>{{member.telephone}}</td>
<td>{{member.accountnumber}}</td>
</tr>
</tbody>
</table>
</div>
I have the following controller
function memberController($scope, $http, $cookieStore) {
var token = $cookieStore.get('token');
var conId = $cookieStore.get('Cont_Id');
var exId = $cookieStore.get('ex_Id');
var member_list = "http://www.vb.com/functions/member_list.html?exchangeid=" + exId +
"&contactid=" + conId + "&token=" + token;
$http.get(member_list)
.success(function(response) {
$scope.details = response;
});
$scope.test_funct = function(id) {
$scope.myid = id;
alert($scope.myid); // getting undefined in alert, i expect the id(eg:1123)
}
}
edit_form.html
<div class="page" data-ng-controller="memberController">
<div class="panel-body" ng-init="test_funct()"></div>
</div>
Please assist me on this. Thanks in advance.
There are 2 things going on here.
First, you should separate controllers for the different views, so you end up with something like this:
<div class="page" data-ng-controller="memberController">
<table>
<!-- your whole big table here -->
</table>
</div>
And your editing form as follows:
<div class="page" data-ng-controller="editController">
<div class="panel-body"></div>
</div>
Notice that you now have two distinct controllers - your "editController" and your "memberController".
The second question then becomes, how do you transfer the selected ID from the list view ("memberController") to the edit view ("editController").
There are 2 ways of doing that.
First, you could use a service shared between the controller:
.factory('SelectedId',function() {
return {};
});
And then in your "member" view, you would set it upon clicking:
{{member.businessname}}
Notice the ng-click, which then needs a function in the memberController and the injected service:
.controller('memberController',function($scope,SelectedId) {
$scope.setId = function(id) {
SelectedId.id = id;
};
});
While the editController retrieves it:
.controller('editController',function($scope,SelectedId) {
$scope.id = SelectedId.id;
});
The above option works well, especially for complex things like shopping carts. If all you are doing is passing an ID, I would just stick it in the URL:
{{member.businessname}}
So that the ID is part of the URL. You then can retrieve it in the "editController":
.controller('editController',function($scope,$routeParams) {
$scope.id = $routeParams.member;
});
assuming you are using ng-route, and your route would look like:
$routeProvider.when('/pages/edit_form/:member',{templateUrl:'/route/to/template.html',controller:'editController'});
In html do that
<td>{{member.businessname}}</td>
...
In app.js or where you define route do that
.when('/edit/:memberid',
{
templateUrl:'partials/edit.html',
controller:'editController'
})
In controller you have to take this id by doing that
app.controller("editController",function($routeParams,$scope){
$scope.memberid= $routeParams.memberid;
//Now use this member id to fetch all data
});

Categories

Resources