Using Django and Jquery - javascript

In addition to this post https://stackoverflow.com/a/17732956 I want to change the order of a list via drag'n'drop and save it afterwards in django backend.
For test purposes and comprehension I've used following fiddle:
http://jsfiddle.net/LvA2z/#&togetherjs=LvHpjIr7L0
and updated the action of the form with my own action. So, instead of script.php, I used action="{% url 'save_order' %}".
In views my function looks like:
def save_order(request):
if (request.method == 'POST'):
list = request.POST['listCSV']
print(list)
Basically I want to change the order of list elements and save it afterwards with the result that after refreshing the page the saved order is given. However I do not know, how pass vars from jquery to django site. When I change the order, I have the sorted list in 'listCSV'. How do I pass this result to django site to save it in db?
EDIT:
If //$("#listsaveform").submit(); is not commented out and I fire this function referenced with my save_order function, I got this error:
jquery-1.10.2.min.js:6 POST http://localhost:8000/overview/saveOrder/ 405 (Method Not Allowed)
EDIT:
Okay, thanks for the hint. I have never worked with ajax and therefore I'm stucking a bit.
I have my list construct:
{% if habits %}
<ul id="sortable">
{% for habit in habits|dictsort:"priority" %}
<li class="ui-state-default">{{habit.title}}</li>
{% endfor %}
</ul>
{% endif %}
and this list construct is sortable with this lines of code:
$(function() {
$( "#sortable" ).sortable();
});
How does look my form?

Here is my solution based on https://impythonist.wordpress.com/2015/06/16/django-with-ajax-a-modern-client-server-communication-practise/.
In JS
// Sort & save order of habits
$(function () {
$('.sort').sortable({
handle: 'button',
cancel: '',
update: function(event, ui) {
var result = $(this).sortable( "serialize", {key: event.target.id});
// alert(result);
var csrftoken = getCookie('csrftoken');
$.ajax({
url : "/overview/saveOrder/", // the endpoint,commonly same url
type : "POST", // http method
data : { csrfmiddlewaretoken : csrftoken,
result : result,
}, // data sent with the post request
// handle a successful response
success : function(json) {
console.log(json); // another sanity check
//On success show the data posted to server as a message
// alert('Your list '+json['result']);
},
// handle a non-successful response
error : function(xhr,errmsg,err) {
console.log("FAILURE");
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
}
});
// var sorted = $( ".selector" ).sortable( "serialize", { key: "sort" } );
// console.log(sorted)
})
//For getting CSRF token
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
and on Django side
def save_habit(request):
print('save_habit')
if (request.method == 'POST'):
if request.is_ajax():
habits = Habit.objects.filter(created_by=request.user.userprofile, is_active=True)
habit_title = request.POST.get('habit_title')
habit_trigger = request.POST.get('habit_trigger')
habit_routine = request.POST.get('habit_routine')
habit_targetbehavior = request.POST.get('habit_targetbehavior')
habit_image = request.POST.get('habit_image')
print(habit_image)
image = habit_image.split('http://localhost:8000/media')
print(image[1])
# TODO: was, wenn routine noch gar nicht existiert? --> speichern
obj_routine = Existingroutine.objects.get(name=habit_routine)
obj_targetbehavior = Targetbehavior.objects.get(name=habit_targetbehavior)
for habit in habits:
habit.priority += 1;
# habit.save();
habit = Habit(created_by=request.user.userprofile, is_active=True,
title=habit_title, trigger=habit_trigger, existingroutine=obj_routine,
targetbehavior=obj_targetbehavior, image=image[1])
#habit.save()
data = {"habit_title":habit_title,
"habit_trigger":habit_trigger,
"habit_routine":habit_routine,
"habit_targetbehavior":habit_targetbehavior };
return JsonResponse(data)
return redirect('display_habits')

Related

How to make API request from HTML select tags?

I need help with this scenario, getting all data from multiple select tag
and use those data to send an API request.
I have these three select tags, and one button to send a request to a news API.
The user needs to select a value from those select tags to set data like "source" and "category".
Example: "https://xxxxxxxxxxxx.org/v2/top-headlines?source='+ source +' + '&category='+ cat +'&apiKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Not sure if this the efficient way.
Below is my js code.
//global variables
var apiUrl = 'https://xxxxxxxxxxxxxxxxxx',
apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxx',
displayRequest = document.querySelector('.displayRequestData'),
requestBtn = document.querySelector('#runApi'), //Btn to display data
newsOpt = document.querySelector('#news-selection'), //news select tag
catOpt = document.querySelector('#news-category'); //category select tag
requestBtn.addEventListener('click', newsRequest); //onclick
function sourceSelected() { //news option
var source = newsOpt !== null ? newsOpt.options[newsOpt.selectedIndex].value : 'the-next-web';
var cat = catOpt !== null ? catOpt.options[catOpt.selectedIndex].value : 'general';
return newsRequest(source, cat);
}
function newsRequest(source, cat) {
axios.get(apiUrl + 'top-headlines?sources=' + source + '&language=' + cat + '&apiKey=' + apiKey)
.then(function (response) {
var reStringify = JSON.stringify(response);
var rejson = JSON.parse(reStringify);
if (rejson.data.status == 'ok'){
console.log(rejson.data.articles[1].source.name);
//console.log(requestBtn);
}
})
.catch(function (error) {
console.log(error);
});
}
By the way, i got this error
VM7472:1 GET https://xxxxxxxxxxxxxxxxxxxxxxxx/v2/top-headlines?sources=[object%20MouseEvent]&language=undefined&apiKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxx 400 (Bad Request)
When you add the event listener to call newsRequest via onClick, the first and only parameter that will be sent to that function is the event object. Therefore, the parameters of source and cat are not passed to newsRequest when they click on the button. (This is why your resulting URL has the [object MouseEvent] in it)
Instead, you might want to call your sourceSelected function in the onClick event which is fetching the current field values and then calling the newsRequest function.
I play around with my code, it's working now.
Note: The news API I'm using not allowing me to mix some data like country, source and langauge. So I try things that only allowed for free account and it works.
requestBtn.addEventListener('click', sourceSelected); //onchange
function sourceSelected() { //news option
var source = newsOpt !== null ? newsOpt.options[newsOpt.selectedIndex].value : 'en';
var cat = catOpt !== null ? catOpt.options[catOpt.selectedIndex].value : 'general';
return newsRequest(source, cat);
} //end of sourceSelected
function newsRequest(source, cat) {
axios.get(apiUrl + 'top-headlines?country=' + source + '&category=' + cat + '&apiKey=' + apiKey)
.then(function (response) {
var reStringify = JSON.stringify(response);
var rejson = JSON.parse(reStringify);
if (rejson.data.status == 'ok') {
console.log(rejson.data.articles[1].source.name);
//console.log(requestBtn);
}
})
.catch(function (error) {
console.log(error);
});
}//newsRequest

How to add csrf token in django with js only without ajax?

I basically want to implement a django view that accepts some json data and then also posts a json data which would be displayed.The confirm group view accepts a list of people via json data , forms a group and then returns the group code back to display.
I was getting the Forbidden(403) CSRF token missing or incorrect Error
I am beginner in django and js so please answer accordingly. Thanking you in advance :)
view.py
import json
def confirm_group(request):
data = json.loads(request.body.decode("utf-8"))
grp = Group()
grp.group_code = group_code_generator()
grp.save()
for i in range(len(data)):
Player = Regplayer.objects.filter(pk=data[i]["pk"])
pl = Enteredplayer()
pl.regplayer = Player
pl.group = grp
pl.save()
return JsonResponse(grp.group_code, safe=False)
script.js
function confirm()
{
var i = 0;
var rows= document.getElementById("group").children;
var num= document.getElementById("group").childElementCount;
if(num==0)
{
}
else
{
// alert("Confirm grouping of "+num+" people?");
for(i=0; i < num; i++)
{
send_name=rows[i].children[0].children[0].innerHTML;
send_gender=rows[i].children[3].children[0].innerHTML;
send_clgname=rows[i].children[1].children[0].innerHTML;
send_sport=rows[i].children[2].children[0].innerHTML;
send_id=rows[i].children[5].innerHTML;
myObj["data"].push({"name":send_name, "gender":send_gender, "college":send_clgname, "sport": send_sport, "pk": send_id});
alert(JSON.stringify(myObj));
}
csrf_token = document.getElementById('csrf_token').innerHTML;
myObj["data"].push({"csrfmiddlewaretoken": csrf_token });
//POST TO BACKEND
// Sending and receiving data in JSON format using POST method
//
var ourRequest = new XMLHttpRequest();
var url = "/confirm_group/";
ourRequest.open("POST", url, true);
ourRequest.setRequestHeader("Content-type", "application/json");
// POST
var data = JSON.stringify(myObj);
ourRequest.send(data);
// Obtain
ourRequest.onreadystatechange = function () {
if (ourRequest.readyState === 4 && ourRequest.status === 200) {
var json = JSON.parse(ourRequest.responseText);
var groupCode = json.groupcode;
//json object received
new_group(groupCode);
}
};
// if success call new_group() else call error_handle()
// new_group();
//error_handle();
//empty json object now
}
}
index.html
<span id="csrf_token" style="display: none;">{{ csrf_token }}</span>
<div class="confirm-modal">
<div class="form">
<p id="modal-text"></p>
<button class="btn1" onclick="confirm()">Confirm</button>
<button class="btn2" onclick="close_modal()">Cancel</button>
</div>
</div>

Ajax POST XMLHttpRequest to DataLayer via Google Tag Manager

Please help me because i'm stuck.
First of all i am a newbie in Ajax and javascript.
So what i have:
I have AJAX calculator form on my website.
I want to track input, dropdown and selection fields and its values in Google Analytics.
I've installed and implemented Google Tag Manager.
I've created custom html tag firing when DOM is ready to pushing output to dataLayer:
<script>
(function() {
var xhrOpen = window.XMLHttpRequest.prototype.open;
var xhrSend = window.XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.open = function() {
this.method = arguments[0];
this.url = arguments[1];
return xhrOpen.apply(this, [].slice.call(arguments));
};
window.XMLHttpRequest.prototype.send = function() {
var xhr = this;
var xhrData = arguments[0];
var intervalId = window.setInterval(function() {
if(xhr.readyState != 4) {
return;
}
dataLayer.push({
'event': 'ajaxSuccess',
'eventCategory': 'AJAX ' + xhr.method,
'eventAction': xhr.url + (xhr.method == 'POST' && xhrData ? ';' + xhrData : ''),
'eventLabel': xhr.responseText
});
clearInterval(intervalId);
}, 1);
return xhrSend.apply(this, [].slice.call(arguments));
};
})();
</script>
5.And I am very happy because I finally got the data in data.layer
{
event: 'ajaxSuccess',
eventCategory: 'AJAX POST',
eventAction:'http://mylocalhosting.local/calculator/ajax_statistic_track;property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html',
eventLabel:'property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html'
}
And finally the Question:
How can I split the data received in URL with strings? I understand that i should create new triggers in GTM and edit the code. But how? JSON.parse?JSON.stringify?:
What i want to have in output:
{
event: 'ajaxSuccess',
eventCategory: 'AJAX POST',
eventAction:'http://mylocalhosting.local/calculator/ajax_statistic_track;property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html',
eventLabel:'property_value=20000&state=1&property_type=1&first_home_buyer=2&are_you_purchasing=2&url=http%3A%2F%2Fnew.sharewood.ru%2Fembed.html'
propertyValue: '20000'
state: '1'
propertyType: '1'
firstHomeBuyer: '2'
}
Since you passed your data as a url you can let GTM handle the parsing. GTM has a "url" type of variable which can also return parts of a url, including a value identified by a query parameter. First you create a dataLayer variable that reads the eventAction (which is in url format). Then you create a new "URL" type variable, set "Component Type" to query key to extract a query variable, set the query parameter name and in "More settings" you select the dataLayer var with the eventAction as "source" parameter. This should look like this to return the value for "propertyValue" (repeat for the other query parameters in the url):

Loop through MongoDB docs?

With a basic AJAX web app running locally, a Form POSTs data through Express/Node.js to MongoDB, and a button onClick responds in a rendering of the Mongo document(s) in a div-box.
Using Swig for templating, onClick of the button is only returning a right-brace to appear in the html div-box.
}
How can this be edited to loop through each MongoDB document?
wrapper.html:
{% for go in allDOCs %}
_wrapperGet('{"getting":"{{ keyName }}"}')
{% endfor %}
..where the ajax posts the wrapper data in index.html:
<!-- For the Returned Fields -->
<div id="theResponse">
</div><!-- /.theResponse -->
console.log(returnValue); is listing the mongoDB documents:
{"keyName":"Here's a Value!"}, {"keyName":"Here's another Value!"}
..from app.js
function getAllDOCs(res) {
db.collection('dbCollectionName').find({}, {"_id":0}).toArray(function (err, docs) {
console.log("Got the DOCs: " + docs);
var returnValue = "";
for (var i = 0; i < docs.length; i++)
{
if (returnValue == "")
{
returnValue = returnValue + JSON.stringify(docs[i]);
}
else
{
returnValue = returnValue + ", " + JSON.stringify(docs[i]);
}
console.log(docs[i]);
}
console.log(returnValue);
res.render('wrapper', { allDOCs: returnValue });
});
}
index.html AJAX json parsing:
function handleFINDbuttonResponse(data)
{
// parse the json string
var jsonObject = JSON.parse(data);
$('#theResponse').append( jsonObject.getting );
}

Why is my jQuery.post() ajax failing when I return one View but does not fail when i return another?

I'm trying to write a straightforward comment poster. I have this code in the controller:
[HttpPost]
[ValidateInput(false)]
public ViewResult Comments(MemberData md, long EntryId, string Comment, long LastId = 0)
{
bool isModerated = true;
bool isLoggedIn = GenesisRepository.IsNotGuest(md.MemberGUID);
bool isCommentAllowed = GenesisRepository.IsPermissionAssigned(md.MemberGUID, "Comments", "Create");
// Moderate comment?
if (moderateGuestComments == false && isLoggedIn == false) isModerated = false;
if (moderateMemberComments == false && isLoggedIn) isModerated = false;
long memberId = (from m in GenesisRepository.Member
where m.MemberGUID == md.MemberGUID
select m.MemberID)
.FirstOrDefault();
if (
EntryId > 0
&& !string.IsNullOrEmpty(Comment)
&& memberId > 0
&& isCommentAllowed)
{
Comments comment = new Comments {
Comment = Comment,
Date = DateTime.Now,
isActive = isModerated ? false : true,
MemberID = memberId,
StreamEntryID = EntryId,
};
if (GenesisRepository.SaveComment(comment))
{
List<Comments> comments = new List<Comments>();
comments = (from c in GenesisRepository.Comments
where c.StreamEntryID == EntryId
&& c.comID > LastId
select c
).ToList();
return View("DisplayComments", comments);
}
}
return View("CommentError", "Unable to post comment.");
}
When everything is fine and the action returns return View("DisplayComments", comments); the $.post() success function is triggered. But, When the action returns return View("CommentError", "Unable to post comment."); The $.post() ajax fails. I don't understand why the $.post() cares which view I'm returning.
Here's my Javascript:
<script type="text/javascript">
$(document).ready(function () {
$("#comments").ajaxError(function (event, request, settings) {
alert("Error requesting page " + settings.url);
});
$("button#submitComment").click(function () {
var commentList = $("#comments");
var lastId = $(".comment h4").last().attr("id");
var commentData = "EntryId=" + $("input#EntryID").val()
+ "&Comment=" + $("textarea#Comment").val()
+ "&LastId=" + lastId;
$.post(
"/find/Comments/Comments",
commentData,
function (data) {
alert("success");
alert(data);
if ($(data).filter(".error").length > 0) {
error = $(data);
$(this).after(error);
}
else {
newComments = $(data);
newComments.filter(".comment").css('display', 'none');
alert(newComments);
commentList.append(newComments);
$(".comment").each(function () {
$(this).slideDown("fast")
});
$("#Comment").attr("value", "");
}
}
);
});
});
</script>
What about this could cause the ajax to fail?
Here's what the two views look like:
View("DisplayComments", comments); (works)
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<Genesis.Domain.Entities.Comments>>" %>
<% foreach (var item in Model) %>
<% { %>
<div class="comment" style="background:#eee; border:1px solid gray; padding:10px 10px 0 10px; margin-bottom:20px;">
<h4 id="<%:item.comID %>"><%: item.Member.ScreenName%> commented on <%: String.Format("{0:f}", item.Date)%></h4>
<p>
<%: item.Comment%>
</p>
</div>
<% } %>
View("CommentError", "Unable to post comment."); (does not work)
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<div class="error">
<%:Model%>
</div>
What about this could cause the ajax post to fail?
If the ajaxError function is triggered this strongly indicates that your controller action returns a status code different than 200, probably 500 which is a strong indication that your controller action throws an exception before ever reaching the last line and be able to return a view.
So here are the steps to do:
Use FireBug
Look at what your server sends as response to the AJAX request
Analyze the response status code and the response contents
Alternative approach:
Put a breakpoint in your controller action
Hit F5
When the controller action is hit step through your code
Observe exactly what happens
Remark: I would very strongly recommend you properly encoding your AJAX input. So instead of:
var commentData = "EntryId=" + $("input#EntryID").val()
+ "&Comment=" + $("textarea#Comment").val()
+ "&LastId=" + lastId;
you definitely should:
var commentData = $.param({
EntryId: $("input#EntryID").val(),
Comment: $("textarea#Comment").val(),
LastId: lastId
});
Note that everytime you use the +, & and = signs when dealing with querystring parameters (no matter what language you are using) you are doing it wrong.

Categories

Resources