I'm a new Django user, stuck on a problem. I'd like to obtain an auto-refresh of my jQuery Datatables datas, showing my new DB content without reload entire html page (using ajax request). I browsed a lot of posts, but did not find my graal...
Here is my Django template.html :
{% block js %}
<script type="text/javascript" language="javascript" class="init">
$(document).ready(function(){
var oTable = $('#db_name').DataTable();
} );
setInterval(function () {
oTable.ajax.reload();
}, 2000 );
} );
</script>
{% endblock %}
My views.py :
def db_update(request):
watch_files()
all_ = db.objects.all()
return render_to_response('supervision.html', {'all_fields': all_})
The problem is an error message "Datatables warning: table id=db_name - Invalid JSON response" displayed each 2sec. I think this is normal because no JSON. Despite this error, the reload is effective : if I do a manual refresh (F5), all new datas added in my DB (the function watch_files create entries in it) appear well in my page.
The ideal, for me, would be to obtain a transparent datas auto-refresh, keeping current sort/page options of the Datatables array.
I tried also this, trying to pass JSON, but without success :
$(document).ready(function() {
var oTable = $('#db_name').DataTable( {
ajax: {{obj_as_json}}
} );
setInterval(function () {
/* oTable.ajax.reload(); */
oTable.fnReloadAjax();
/* oTable.fnDraw(); */
}, 2000 );
} );
def db_update(request):
watch_files()
all_ = db.objects.all()
jsondata = serializers.serialize('json', all_)
return render_to_response('supervision.html', {
'obj_as_json':json.dumps(jsondata),
'all_fields': all_})
If anybody could help me, it would be great.
Thks, Christophe
render_to_response('supervision.html') always return an html content that produced by supervision.html template.
You need to return JsonResponse object, that would contain json data only.
from django.http import JsonResponse
def db_update(request):
watch_files()
all_ = db.objects.all()
if request.is_ajax():
jsondata = serializers.serialize('json', all_)
return JsonResponse(jsondata)
else:
return render_to_response('supervision.html', {
'all_fields': all_})
In addition, you need to transform your all_ variable to looks like datatables expects
{
"data": [
[ "column1_val",
"column2_val",
...
],
]
}
I suggest you take a look to https://github.com/pivotal-energy-solutions/django-datatable-view implementation
Related
I would like to pass some data from my Python view function to a JS script using HTML. That's my view function
def home(request):
if request.method == 'POST':
params = GameOfLifeForm(request.POST)
if params.is_valid():
starting_grid = get_starting_grid(params.cleaned_data)
to_html = {
'animation': True,
'gameoflifeform': params,
'start_grid': starting_grid,
}
else:
to_html = {
'animation': False,
'warning_msg': 'Something went wrong. Try once again.'
}
return render(request, 'get_animations/home.html', to_html)
else:
form = GameOfLifeForm()
return render(request, 'get_animations/home.html', {'gameoflifeform': form})
My form contains four parameters, one of them is called iterations and that is the one I would like to pass to JS script. Moreover I would like to pass start_grid.
I tried to do it in the following way in my HTML file
{{ start_grid | json_script:"start-grid" }}
<script
type="text/javascript"
src="{% static 'js/runGameOfLife.js' %}"
></script>
Then in my JS script I wrote
var startGrid = JSON.parse(document.getElementById("start-grid").textContent);
console.log(startGrid);
Worked perfectly, I got the grid printed out in my console. Similar I could grab iterations from HTML
{{ gameoflifeform.iterations.value | json_script:"iterations"}}
<script
type="text/javascript"
src="{% static 'js/runGameOfLife.js' %}"
></script>
When I tried to add both variables into my JS script it didn't work.
{{ gameoflifeform.iterations.value | json_script:"iterations"}}
{{ start_grid | json_script:"start-grid" }}
<script
type="text/javascript"
src="{% static 'js/runGameOfLife.js' %}"
></script>
How can I pass several variables into my JS script? What would be the best way of doing it?
Best to use some combination of ajax and view functions, if you learn this pattern you can accomplish a lot:
views.py
def my_view_function(request):
''' this method accepts data from the front end,
processes it, and returns a response '''
# unpack post request:
first_value = request.POST.get('first_key')
# do some logic:
...
# pack response
response = {
"second_key" : "second_value"
}
# return a json response:
return JsonResponse(response)
scripts.js
function post_request() {
/* set an event to trigger this method
this method will then send data to the backend
and process the response */
// send an ajax post request:
$.ajax({
type : 'POST',
url : 'the_url',
data : {
first_key : 'first_value'
},
success : function(response) {
// unpack response
second_value = response.second_key
// do some logic
...
}
});
}
Once you understand this, you will be able to seamlessly pass data back and forth between the frontend and backend. Let me know if you need more details.
Solution:
My mistake was that the url attribute doesn't just add the string given to 127.0.0.1 but to the current url, and so the url for the Like view was supposed to be 127.0.0.1/article/article_id/like-article-commm
I wrote a django app that has articles and im trying to add a like functionality, I added the code in the bottom and nothing happens. No error just nothing in the database or the html code changes. Any idea what is the problem?
The relevent part of the html/javascript code:
<head>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
</head>
<button id='like-button' color = 'black'> Like </button>
<script type="text/javascript">
$('#like-button').click(function(){
var article_id = '{{ article.id }}';
var user_id = '{{ user.id }}';
var like_dislike = True;
$.ajax(
{
type:"GET",
url: "like-article-commm",
data:{
article_id: article_id,
user_id: user_id,
like_dislike: like_dislike
},
success: function( data )
{
$('#like-button').css('color', 'blue'); } }) });
</script>
The like-article-comm View:
def Like_Article_View(request):
if request.method == 'GET':
article_id = int(request.GET['article_id'])
likedarticle = Article.objects.get(id = article_id)
user_liked_id = int(request.GET['user_id'])
userliked = User.objects.get(id = user_liked_id)
like_dislike_0 = request.GET['like_dislike']
like_object_list = Like_Article.objects.filter(article_liked = likedarticle, user_liked = userliked)
if like_object_list.count() > 0:
existing_like = like_object_list.filter()
if existing_like.like_dislike == like_dislike_0:
return HttpResponse('success')
existing_like.like_dislike = like_dislike_0
existing_like.save()
like_new_object= Like_Article(article_liked=likedarticle, user_liked=userliked, like_dislike=like_dislike_0)
like_new_object.save()
return HttpResponse('success')
else:
return HttpResponse("unsuccesful")
urls.py file:
from django.urls import path
from . import views
from .views import ArticleListView, ArticleDetailView, ArticleCreateView, ArticleUpdateView, ArticleDeleteView
urlpatterns = [
path('', ArticleListView.as_view(), name="home-comm"),
path('article/<int:pk>/', ArticleDetailView.as_view(), name="article-comm"),
path('like_article/', views.Like_Article_View, name='like-article-commm'),
]
I can add like objects to the database manually.
--update--
After some discussion, we figure out that frontend ajax is not communicating with the backend properly. With chrome devtools we managed to pin point where the issue lies.
have you enabled CORS cross site resource sharing?
I have multiple input tags, my task is to collect the values entered by the user and send it back to the server. I am using Django as my framework. I am successful in sending the data to the client side (javascript).
To return back the data from javascript function to my python function, I used XMLHttpRequest.
I have added my code below:
<html>
<head>
<style>label{ text-align:center; width:250px; color:blue; display:inline-block}</style>
<script type="text/javascript" src="'+url_read+'"></script>
<script>
function submit_this()
{
var i,j;var arr=[];
for(i=0; i<Hello.length; i++)
{
arr[i]=[];
for(j=0;j<Hello[i].length; j++)
{
arr[i].push(document.getElementById(Hello[i][j]).value);
}
}
alert(document.getElementById(Hello[1][0]).value);
xmlHttpReq = new XMLHttpRequest();
xmlHttpReq.open('POST', '/button_click',true);
xmlHttpReq.send('w=' + encodeURI(arr));
}
</script>
</head>
<body>
<center>
<button id="submit_button" onclick="submit_this();" value="Submit">Submit</button>
</center>
</body>
</html>
The above code is stored in a string called html_string.
Hello is a json object read from the file denoted by the varible url_read. It was dumped using Python.
The plan was to use HttpResponse to send the html_string and render the html page in return.
I understand that I need to make one POST function in one of the classes in views.py. But unable to understand how to approach this problem.
I have to somehow send the javascript data structure named arr back to the server side. The main doubt is where can I put my code where I can read the value posted by the javascript function.
I want to navigate to a new page once submit button has been pressed and in Django each url has a new function (in views.py) associated with it. Should I place it in that ?
Here is an example where in I am sending values to (Django)python server using JS, and receiving html rendered template.
I am using ul tag with id #Nearby to load html inside an html.
Ajax success is returning html from django view rendered through url endpoint '/getGopoints/'
template.html
<div class="row">
<div>
<ul id="Nearby">
</ul>
</div>
</div>
<script>
$(document).ready(function(){
$('#dataTables-example1').DataTable({
responsive: true
});
getLocation();
});
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
}
function showPosition(position) {
$.ajax({
url : '/getGopoints/', // the endpoint
type : 'GET', // http method
data : { 'lat' : position.coords.latitude,
'lon' : position.coords.longitude,
'csrfmiddlewaretoken': '{{csrf_token}}'
}, // data sent with the post request
// handle a successful response
success : function(data) {
$('#Nearby').html(data);
},
dataType: 'html'
});
}
</script>
urls.py
url(r'^getGopoints/$',views.getGopoints, name='getGopoints'),
views.py
def getGopoints(request):
lat = str(request.GET['lat'])
lon = str(request.GET['lon'])
pnt=fromstr('POINT(%s %s)' %(lon,lat))
with_in_distance = 20
go_points = GoPoint.objects.filter(point__distance_lte=(pnt, D(km=with_in_distance)))
context = RequestContext(request,
{'go_points':go_points,
'with_in_distance':with_in_distance,
})
return render_to_response('nearby.html',
context_instance=context)
I'm trying to use flask with url_for. The problem is that when I try to launch an alert with the value of the javascript variable everything seems ok, but when I try to launch a alert with the url_for the content of the variable is not printed. What I'm doing wrong? or What is missing in my code?
How can I pass a JavaScript variable into the url_for function?
html code:
<a class="dissable_user_btn" data-user_id="{{user.id}}" href="#" title="Change Status"><i class="fa fa-plug"></i>
</a>
JS Code:
<script type="text/javascript">
$(document).ready(function(){
$('.dissable_user_btn').click(function( event ) {
var user_id = $(this).data("user_id")
alert(user_id) //everything ok
alert ('{{url_for('.dissable', _id=user_id)}}'); //dont print the valur of user_id
</script>
Short answer: you can't. Flask & Jinja2 render the template on the server side (e.g. Flask is translating all of the {{ }} stuff before it sends the HTML to the web browser).
For a URL like this where you're including a variable as part of the path you'd need to build this manually in javascript. If this is an XHR endpoint I'd recommend using GET/POST to transfer the values to the server as a better best practice than constructing the URL this way. This way you can use Jinja:
$(document).ready(function(){
var baseUrl = "{{ url_for('disable') }}";
$('.dissable_user_btn').click(function(event) {
var user_id = $(this).data("user_id");
// first part = url to send data
// second part = info to send as query string (url?user=user_id)
// third parameter = function to handle response from server
$.getJSON(baseUrl, {user: user_id}, function(response) {
console.log(response);
});
});
});
I found another solution for this. My problem started when I needed to pass a variable with space.
First I created a function to remove trailing and leading spaces
function strip(str) {
return str.replace(/^\s+|\s+$/g, '');}
After that, I used the function and encoded the URL
<script type="text/javascript">
$(document).ready(function(){
$('.dissable_user_btn').click(function( event ) {
var user_id = $(this).data("user_id")
alert(user_id)
user_id = strip(user_id).replace(" ","%20");
alert ('{{url_for('.dissable', _id='user_id')}}.replace('user_id',user_id);
</script>
It worked pretty nice for me!
This is how I applied to my problem
<script>
function strip(str) {
return str.replace(/^\s+|\s+$/g, '');}
$(document).ready(function() {
$('#exportcountry').click(function() {
var elemento = document.getElementById("countryexportbtn");
var country = strip(elemento.textContent).replace(" ","%20");
$('#exportevent').load("{{ url_for('get_events',country = 'pais') }}".replace('pais',country));
});
});
</script>
I am getting an error saying unexpected token while trying for passing id from django template to reatjs for uploading multiple images to its associated foreign key object. The error is shown as unexpected token }. In depth it is shown as
in console
var uploadUrl = {
url:
};
What i am trying to do is , I have created a listing page with multiple form and it is entirely developed using reactjs. I want user to fill the data about room and upload multiple images related to their room. There are two models one with room info and another gallery(multiple image is associated with one rent). I wanted the uploaded images be associated with its rent so i coded it as below
urls.py
urlpatterns = [
url(r'^add/$', AddView.as_view(), name="add"),
url(r'^add/space/$', AddSpaceView.as_view(), name="addSpace"),
url(r'^upload/image/(?P<pk>\d+)/$', ImageUpload, name="ImageUpload"),
]
views.py
def ImageUpload(request,pk=None): // for saving images only to its asscoiated rent
if request.POST or request.FILES:
rental = Rental.objects.get(id=pk)
for file in request.FILES.getlist('image'):
image = GalleryImage.objects.create(image=file,rental=rental)
image.save()
return render(request,'rentals/add.html')
class AddView(TemplateView): // for listing page
template_name = 'rentals/add.html'
class AddSpaceView(View): // for saving data to database except image
def post(self,request,*args,**kwargs):
if request.POST:
rental = Rental()
rental.ownerName = request.POST.get('ownerName')
rental.email = request.POST.get('email')
rental.phoneNumber = request.POST.get('phoneNumber')
rental.room = request.POST.get('room')
rental.price = request.POST.get('price')
rental.city = request.POST.get('city')
rental.place = request.POST.get('place')
rental.water = request.POST.get('water')
rental.amenities = request.POST.get('amenities')
rental.save()
return HttpResponseRedirect('/')
listing.js(ajax code for uploading multiple image)
var image = [];
image = new FormData(files);
$.each(files,function(i,file){
image.append('image',file);
});
$.ajax({
url:"/upload/image/", // want to used id over here that is passed from add.html script tag so that image will be uploaded to its associated foriegn key object
data:image,
contentType:false,
processData:false,
type:'POST',
mimeType: "multipart/form-data",
success: function(data) {
console.log('success');
}
});
}
add.html page
<div id="listing">
</div>
{% include 'includes/script.html'%}
<script type="text/javascript">
var uploadUrl = {
url: {% for rental in object_list %} { "id": {{ rental.id }} } {% endfor %} // here is an error
};
console.log('url is', url);
$(function() {
app.showListingSpaceForm("listing");
});
</script>
The code might explained what i was trying to achieve. If models.py is also required for more scrutiny then i will update it.
You're missing a fundamental piece: TemplateView has no concept of object_list, you have to populate it yourself. If your view is simple enough use ListView and set your model property. If not, you have to manually populate the object list, something like this:
def get_context_data(self, **kwargs):
context['object_list'] = MyModel.objects.all()
That was just an example to set you on the right path.