Django url rewrites and passing a parameter from Javascript - javascript

As a bit of a followup question to my previous , I need to pass a parameter to a view. This parameter is not known until the JS executes.
In my URLConf:
url(r'^person/device/program/oneday/(?P<meter_id>\d+)/(?P<day_of_the_week>\w+)/$',
therm_control.Get_One_Day_Of_Current_Thermostat_Schedule.as_view(),
name="one-day-url"),
I can pass it this URL and it works great! ( thanks to you guys).
http://127.0.0.1:8000/personview/person/device/program/oneday/149778/Monday/
In My template I have this:
var one_day_url = "{% url personview:one-day-url meter_id=meter_id day_of_the_week='Monday' %}";
In my javascript:
$.ajax({
type: 'GET',
url: one_day_url ,
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
When this triggers it works fine except I dont necessarily want Monday all the time.
If I change the javascript to this:
var one_day_url = "{% url personview:one-day-url meter_id=meter_id %}";
and then
$.ajax({
type: 'GET',
url: one_day_url + '/Monday/',
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
I get the Caught NoReverseMatch while rendering error. I assume because the URLconf still wants to rewrite to include the ?P\w+) .
I seems like if I change the URL conf that breaks the abailty to find the view , and if I do what I do above it gives me the NoREverseMatch error.
Any guidance would be appreciated.

I usually do something along the lines of
var one_day_url = "{% url personview:one-day-url meter_id=meter_id day_of_the_week='REPLACE_ME' %}";
// ...
url: one_day_url.replace('REPLACE_ME', 'Sunday')

you may want to use this kind of project which is meant to answer to this precise question...
notice: it may help hacker to map the website:
https://github.com/Dimitri-Gnidash/django-js-utils
When I don't use this project I put a default value in the url and replace it by correct value.
so use a complete reverse then:
url: one_day_url.replace('/Monday/','/Caturday/')
and even if you replace monday by monday it will works...
note: this ugly haks will fail if your default value is already sooner in the url so use it consequently.

Why not just pass them in as part of the request data. You can use the jQuery get function and pass them in as paramaters.
$.get("{%url personview%}", {'meter_id':"meter_id", "day_of_the_week":"monday" ...}, function(){do stuff when info is returned});
Then in your view you can do:
meter = request.GET['meter_id']
This will allow you to use it in your view.

I had a similar question. I wanted to open a URL when someone clicked a button. For what it's worth, here is how I handled this situation.
Define the URL as an attribute:
{% for article in articles %}
<button data-article-url="{% url view_article article.id %}">
Read Article #{{ article.id }}
</button>
{% endfor %}
Using jQuery, read the attribute and carry on:
var article_url = $(this).attr("data-article-url");
$.ajax({
url: article_url,
...
});

You could use tokens in your url and pass it as a variable to your module:
<script src="{{ STATIC_URL }}js/my-module.js"></script>
<script>
$(function(){
MyModule.init(
"{% url personview:one-day-url meter_id='0000' day_of_the_week='{day}' %}"
);
});
</script>
// js/my-module.js
var MyModule = {
init: function(one_day_url) {
var id = 1, day = 'Saturday';
this._one_day_url = one_day_url;
console.log(this.one_day_url(id, day));
$.ajax({
type: 'GET',
url: this.one_day_url(id, day),
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
},
one_day_url: function(meter_id, day) {
return this._one_day_url.replace('0000', meter_id).replace('{day}', day);
}
};
Notice that token should match the regex type to resolve successfully (I can't use {meter_id} because it's defined with \d+).
I'm a little bit unsatisfied with this solution and I ended by writing my own application to handle javascript with django: django.js. With this application, I can do:
{% load js %}
{% django_js %}
{% js "js/my-module.js" %}
// js/my-module.js
var MyModule = {
init: function() {
var id = 1, day = 'Saturday';
console.log(
Django.url('personview:one-day-url', id, day),
Django.url('personview:one-day-url', [id, day]),
Django.url('personview:one-day-url', {
meter_id: id,
day_of_week: day
})
);
$.ajax({
type: 'GET',
url: Django.url('personview:one-day-url', id, day),
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
}
};
$(function(){
MyModule.init();
});

Related

Refresh content in a for loop using jquery in Django

I am creating a website that allows users to search for a list of papers. Once a list of papers is returned, the user can click "like" or "dislike" to one or more papers. The like count should dynamically update as the user click the like button.
I am using jquery to handle the dynamic update of the like count. However, I am not sure how to tell the success function in the ajax WHICH id to update. The reason is that the id is generated on the fly, and it is determined by which papers are returned as search results to the user.
So far, I have the following in the template:
{% for result in results %}
<li >
{{ result.title}},
<span class="like_span fa fa-thumbs-up"></span>
<strong id="like_count_{{ result.pk }}">{{result.likes}} </strong>
</li>
{% endfor %}
As you can see, i specify the id of the part where I want the dynamic update to happen as "like_count_{{ result.pk }}". I am not sure if this is the best way to go about it.
The jquery part looks like this:
<script>
$(document).ready(function(){
$(".like_button").click(function(){
$.ajax({
type: "GET",
data: {'pk': $(this).data('pid'),
'liked': $("span").hasClass('fa fa-thumbs-up') },
url: "{% url 'search:paperpreference' %}",
success: function(response) {
var pk = $(this).data('pid');
$(?????).html(response.likes )
},
error: function(response, error) {
alert(error);
}
});
});
});
</script>
Simply put, I don't know how can i specify the ????? part such that when success, the new like count is only updated to that specific paper, not the first paper in the loop.
The views.py has the following so far:
def paperpreference(request):
# if request.method == "GET":
pid = request.GET['pk']
paper = Paper.objects.get(pk=pid)
likes = paper.likes + 1
paper.likes = likes
paper.save()
data = {'likes': paper.likes}
return JsonResponse(data)
I am new to Jquery, any help would be much appreciated!
Thanks to suggestions by #dirkgroten, the like count can now be dynamically updated by the following jquery function. The trick is to move the pk declaration to before the ajax.
<script>
$(document).ready(function(){
$(".like_button").click(function(){
var pk = $(this).data('pid')
$.ajax({
type: "GET",
data: {'pk': pk,
'liked': $("span").hasClass('fa fa-thumbs-up') },
url: "{% url 'search:paperpreference' %}",
success: function(response) {
$("#like_count_"+ pk).html(response.likes )
},
error: function(response, error) {
alert(error);
}
});
});
});
</script>
another option is return the id from the server.
def paperpreference(request):
# if request.method == "GET":
pid = request.GET['pk']
paper = Paper.objects.get(pk=pid)
likes = paper.likes + 1
paper.likes = likes
paper.save()
data = {'likes': paper.likes,'pid':pid}
return JsonResponse(data)
<script>
$(document).ready(function(){
$(".like_button").click(function(){
var pk = $(this).data('pid')
$.ajax({
type: "GET",
data: {'pk': pk,
'liked': $("span").hasClass('fa fa-thumbs-up') },
url: "{% url 'search:paperpreference' %}",
success: function(response) {
$("#like_count_"+ response.pid).html(response.likes )
},
error: function(response, error) {
alert(error);
}
});
});
});
</script>

Django/Ajax/Jquery running two ajax requests in the same event.

I think I'm really close to getting this working but I need some help with the Jquery as everything works as intended on the second click and beyond. It just doesn't work on the first click.
I'm basically trying to replicate the youtube like and dislike buttons. So you click the thumbs up, it shows +1 and if you click it again it subtracts one. All that logic works until I get into the AJAX and Jquery portion.
I have one ajax request that adds the user to the "liked" ManyToManyField. Then I have one apiview that I'm connecting to just produce the upvote and downvote count, then displaying that into the template.
This all works, but again the first click produces the correct result in the console. The second click produces the "opposite" result in the template and correct result in the console. Then of course if I reload every time I click "up" it works as intended but i'm trying to prevent reloading.
template - Jquery/Ajax
$(".upvote-btn").click(function(e){
e.preventDefault()
var this_ = $(this)
var upvoteToggleUrl = this_.attr("data-href")
var voteCountAPIUrl = "{% url 'streams:vote-count' streampost.pk %}";
$.ajax({
url: upvoteToggleUrl,
method: 'GET',
data: {},
success: function(data){
}, error: function(error){
console.log(error)
console.log("error")
}
})
$.ajax({
url: voteCountAPIUrl,
method: 'GET',
data: {},
success: function(data){
console.log(data.upvotes)
console.log(data.downvotes)
$('.upvote-count').text(data.upvotes);
}, error: function(error){
console.log(error)
console.log("error")
}
})
})
HTML
<p>
Upvotes
<div class="upvote-count" data-href="{% url 'streams:vote-count' streampost.pk %}">
{{ streampost.upvotes.count }}
</div>
<a class="upvote-btn" data-href='{{ streampost.get_api_upvote_url }}'
href='{{ streampost.get_upvote_url }}'>Up</a>
Downvotes {{ streampost.downvotes.count }}
</p>
It seems to me like you want the upvote request to complete first before you retrieve the upvote count. To do that, you need to make the second request in the callback of the first:
$(".upvote-btn").click(function(e){
e.preventDefault()
var this_ = $(this)
var upvoteToggleUrl = this_.attr("data-href")
var voteCountAPIUrl = "{% url 'streams:vote-count' streampost.pk %}";
$.ajax({
url: upvoteToggleUrl,
method: 'GET',
data: {},
success: function(data){
$.ajax({
url: voteCountAPIUrl,
method: 'GET',
data: {},
success: function(data){
console.log(data.upvotes)
console.log(data.downvotes)
$('.upvote-count').text(data.upvotes);
}, error: function(error){
console.log(error)
console.log("error")
}
})
}, error: function(error){
console.log(error)
console.log("error")
}
})
})

Calling [HTTPPost] from Javascript ASP.NET

I am using a method in my controller which imports data from an API. This method I am wanted to be called from two locations. First the view (currently working) and secondly a javascript function.
Start of controller method:
[ActionName("ImportRosters")]
[HttpPost]
public ActionResult PerformImportRosterData(int id, int? actualLength, int? rosterLength)
{
var authenticator = Authenticator(id);
var rosters = authenticator.Api().RosterData().ToDictionary(x => x.Id);
var databaseRosterDatas = SiteDatabase.DeputyRosterData.Where(x => x.SiteID == id)
.ToDictionary(x => x.Id);
Javascript Function:
$("#btnDeputyRunNowUpdate").click(function() {
$("#btnRunDeputyNow").modal("hide");
ActualLength = $("#actualRunLength").val();
RosterLength = $("#rosterRunLength").val();
$.ajax({
type: "POST",
url: "/deputy/PerformImportRosterData",
data: { SiteIDRoster, ActualLength, RosterLength }
});
SiteIDRoster = null;
location.reload();
$("#btnRunDeputyNow").modal("hide");
toast.show("Import Successful", 3000);
});
All values are being set but i am getting a 404 error on the url line
POST https://example.org/deputy/PerformImportRosterData 404 ()
I need a way to be able to call this c# method from both html and JS
This can be done if you will modify the URL in your AJAX. It should look something like
url: '<%= Url.Action("YourActionName", "YourControllerName") %>'
or
url: #Url.Action("YourActionName", "YourControllerName")
one more thing, I don't see if you do anything with the result of the call. your script does not have success part
success: function(data) {//do something with the return}
and would be very helpful to have error handler in your call.
full example on how AJAX should look like:
$.ajax({
url: "target.aspx",
type: "GET",
dataType: "html",
success: function (data, status, jqXHR) {
$("#container").html(data);
alert("Local success callback.");
},
error: function (jqXHR, status, err) {
alert("Local error callback.");
},
complete: function (jqXHR, status) {
alert("Local completion callback.");
}
})
For a good tutorial on AJAX read this document
Change after Comment:
my current code is below:
$("#btnDeputyRunNowUpdate").click(function() {
$("#btnRunDeputyNow").modal("hide");
ActualLength = $("#actualRunLength").val();
RosterLength = $("#rosterRunLength").val();
$.ajax({
type: "POST",
url: '<%= Url.Action("PerformImportRosterData", "DeputyController") %>',
data: { SiteIDRoster, ActualLength, RosterLength },
success: function(data) {
console.log(data);
console.log("TESTHERE");
}
});
}
UPDATE:
Noticed one more thing. Your parameters in the controller and AJAX do not match. Please try to replace your a few lines in your AJAX call with:
url: "/deputy/PerformImportRosterData",
data: { id: yourIDValue, actualLength: youractualLengthValue,
rosterLength :yourrosterLengthValue }
remember to set all variable values in javascript , if they have no values set them = to null.
Can you try copy paste code below
$.ajax({
type: "POST",
url: "/deputy/PerformImportRosterData",
data: { SiteIDRoster:999, ActualLength:1, RosterLength:2 }
});
And let me know if it wall cause any errors.
After attempting to solve for a few days, I created a workaround by creating two methods for importing the data. one for the httpPost and the second for import calling from javascript.
Not a great solution but it works. Thanks for your help Yuri

What's the optimal way of making these AJAX GET requests with jQuery & JSON API?

I'm outputting API data on separate pages coming from different end point urls, ie. https://api.server.com/first, https://api.server.com/second, etc.
The code is working, but it seems awfully redundant and I'm sure there's a better way of expressing this that's more optimal and faster:
var $rubys = $('#rubys');
$(function () {
$('#loading-rubys').show();
$.ajax({
type: 'GET',
url: 'https://api.server.com/first/',
success: function(rubys) {
$.each(rubys, function(i, ruby) {
$rubys.append('$'+parseFloat(ruby.price).toFixed(2)+' |
$'+parseFloat(ruby.attribute).toFixed(0));
});
},
complete: function(){
$('#loading-rubys').hide();
}
})
});
var $emeralds = $('#emeralds');
$(function () {
$('#loading-emeralds').show();
$.ajax({
type: 'GET',
url: 'https://api.server.com/second/',
success: function(emeralds) {
$.each(emeralds, function(i, emerald) {
$emeralds.append('$'+parseFloat(emerald.price).toFixed(2)+' |
$'+parseFloat(emerald.attribute).toFixed(0));
});
},
complete: function(){
$('#loading-emeralds').hide();
}
})
});
The following:
var $rubys = $('#rubys');
$('#loading-rubys').show();
are set for each post page using YAML front-matter (Jekyll) like so:
---
title: Post about Ruby
var-id: rubys
load-id: loading-rubys
---
and output them in HTML:
<div id="{{ page.var-id }}">
<div id="{{ page.load-id }}">
<img src="/assets/img/loading.svg"/>
</div>
</div>
Current workflow
So basically whenever I create a new post, I:
Set the var-id and load-id custom parameters for each post in the front-matter
Create a new function to include those and make a new GET request to the respective url, ie. https://api.server.com/third/, https://api.server.com/fourth/.
How would you write this better?
Something like this could help.
function getGems(gems,gemsURL) {
var $gems = $('#'+gems);
$('#loading-'+gems).show();
$.ajax({
type: 'GET',
url: gemsURL,
success: function(data) {
$.each(data, function(i, v) {
$gems.append('$'+parseFloat(v.price).toFixed(2)+' |
$'+parseFloat(v.attribute).toFixed(0));
});
},
complete: function(){
$('#loading-'+gems).hide();
}
});
}
$(function () {
getGems('rubys','https://api.server.com/first/');
getGems('emeralds','https://api.server.com/second/')
});

jquery function not redirecting url

I am working with codeigniter and jquery. I am using ajax to send some info to a codeigniter function to perform a db operation , in order to update the page. After the operation is complete I am trying to refresh the page. However the refresh works inconsistently and usually I have to reload the page manually. I see no errors in firebug:
var message = $('#send_message').val()
if ((searchIDs).length>0){
alert("searchIDs "+searchIDs );
$.ajax({
type: "POST",
url: "AjaxController/update",
data:{ i : searchIDs, m : message },
dataType: 'json',
success: function(){
alert("OK");
},
complete: function() {
location.href = "pan_controller/my_detail";
}
})
.done(function() { // echo url in "/path/to/file" url
// redirecting here if done
alert("OK");
location.href = "pan_controller/my_detail";
});
} else { alert("nothing checked") }
break;
How can I fix this?
addendum: I tried changing to ;
$.ajax({
type: "POST",
url: "AjaxController/update",
data:{ i : searchIDs, m : message },
dataType: 'json',
.done(function() { // echo url in "/path/to/file" url
// redirecting here if done
alert("REFRESHING..");
location.href = "pan_controller/my_detail";
});
}
})
This is just defaulting to the website homepage. again, no errors in firebug
Add the window object on location.href like this:
window.location.href = "pan_controller/my_detail";
Try to use full path like
$.ajax({a
type: "POST",
url: "YOURBASEPATH/AjaxController/update",
data:{ i : searchIDs, m : message },
dataType: 'json',
.done(function() { // echo url in "/path/to/file" url
// redirecting here if done
alert("REFRESHING..");
location.href = "YOURBASEPATH/pan_controller/my_detail";
});
}
})
BASEPATH should be like this "http://www.example.com"
Try disabling the csrf_enabled (config/config.php) and trying it. If that works, then re-enable the protection and, instead of compiling data yourself, serialize the form; or, at least include the csrf hidden field codeigniter automatically adds. You can also use GET to avoid the CSRF protection, but that's least advisable of of the solutions.

Categories

Resources