I am sending some data from html template to views.py via ajax.From the id sent to views.py I am creating sql records. However I was wondering if there is any way to send data from views.py to template to notify that the data is added to sql.
code-
$('#tn1').click(function(){
var msg='';
alert('inside alert');
if ($('textarea#message') != "") {
var message = $('#notesarea').val();
alert(message);
msg=message;
}
$.ajax({
url: 'post_note',
data: {
'note': msg
},
success: function (data) {
alert(data)
}
});
views.py
def post_note(request,id):
post_id = request.GET['note']
print(post_id)
//sql insertion code,once its done i want to notify to the front end..print some alert message.
return render(request, './profile.html')
You should use something like JSONResponse in your view, then you data will appear in success function
success: function (data) {alert(data)}
You can do this using JQuery Ajax in the template and by creating an "API view" in your views.py that is basically just a regular view that returns a JSONResponse after checking to verify the request is Ajax. As an example of the "API" option, using JQuery:
In your views.py file (using the GET method which you should only use if the note is short, will fit into the URL bar, and if you don't have major security concerns, otherwise see the POST example at bottom):
from django.http import JsonResponse
def post_note_api(request):
data = {}
if request.GET.get('post_note', None) is not None:
post_note = request.GET.get('post_note')
# save the note and indicate success
data['result'] = True
data['message'] = "Note posted successfully"
...
if request.is_ajax():
return JsonResponse(data)
else:
return HttpResponseBadRequest()
In your urls.py:
...
path('/api/post_note/', post_note_api, name="post_note_api"),
...
In your template (if you are using the GET method):
<script type="text/javascript">
$("#tn1").click(function(){
var message = $("#myTextArea").val();
$.ajax({ url: '{% url 'post_note_api' %}?post_note=' + message,
type: "GET",
dataType: "json",
cache: false
}).done(function(data) {
if (data.result === true){
alert(data.message);
}
});
});
});
</script>
If you are using the POST method instead of GET (which is probably the better option here):
<script type="text/javascript">
$("#tn1").click(function(){
var csrfToken = $( "input[name='csrfmiddlewaretoken']");
var message = $("#myTextArea").val();
$.ajax({ url: '{% url 'post_note_api' %}',
type: "POST",
dataType: "json",
data: {'post_note':message, 'csrfmiddlewaretoken':csrfToken.val()},
cache: false
}).done(function(data) {
if (data.result === true){
alert(data.message);
}
});
});
});
</script>
For the POST method, in your view just change request.GET.get('post_note') ... to request.POST.get('post_note') ... like so:
from django.http import JsonResponse
def post_note_api(request):
data = {}
if request.POST.get('post_note', None) is not None:
post_note = request.POST.get('post_note')
# save the note and indicate success
data['result'] = True
data['message'] = "Note saved successfully"
...
if request.is_ajax():
return JsonResponse(data)
else:
return HttpResponseBadRequest()
When you are sending data via POST don't forget to pass along your CSRF token as in the example above. This assumes you have a form on the page you can get it from, otherwise you can use something like this to get it:
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 = cookies[i].trim();
// 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;
}
var csrftoken = getCookie('csrftoken');
If you don't want to deal with the CSRF token, you can mark the view with the #csrf_exempt decorator and remove the 'csrfmiddlewaretoken' data element from the Ajax call in the template, but it may not be ideal or the most secure. An example of that:
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
#csrf_exempt()
def post_note_api(request):
...
Now, without knowing more, this is basically just pseudocode (plus I just wrote this off the top of my head so it may have errors). If you post more details I can update my answer, but I think this should get you started.
I have used below for sending data from HTML to views.py and then return a success response back to HTML. Hope this can be helpful:)
HTML Code:
<button class="button primary fit small" onclick="saveContent()">Save</button>
Javascript Code:
<script>
function saveContent(){
var code =editor.getSession().getValue();
var URL = "{% url 'save' %}";
var data = {'code': code};
$.post(URL, data, function(response){ // This is the main function that will help you
if(response === 'success'){ window.location.reload(); }
else{ alert('Error! :('); }
});
}
</script>
View.py:
def save_content(request):
if request.method == 'POST':
if 'code' in request.POST:
file_data = request.POST['code']
return HttpResponse('success')
Related
I saw a similar question but the answer is rather vague. I created a function based view for updateItem. I am trying to get json data to load based on my request. but am getting the error -> object has no attribute 'data'
Views.py file:
def updateItem(request):
data = json.loads(request.data)
productId = data['productId']
action = data['action']
print("productID", productId, "action", action)
customer = request.user.customer
product = Product.objects.get(id=productId)
order, created = Order.objects.get_or_create(customer=customer,complete=False)
orderItem, created = OrderItem.objects.get_or_create(order=order, product=product)
if action == 'add':
orderItem.quantity = (orderItem.quantity + 1)
elif action == 'remove':
orderItem.quantity = (orderItem.quantity - 1)
orderItem.save()
if orderItem.quantity <= 0:
orderItem.delete()
return JsonResponse("Item was added!", safe=False)
JS File:
function updateUserOrder(productId, action) {
console.log('User is logged in...');
let url = '/update_item/';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({ productId: productId, action: action }),
})
.then((res) => {
return res.json();
})
.then((data) => {
console.log('data', data);
});
}
urls python file:
urlpatterns = [
path("",views.store,name="store"),
path("cart/",views.cart,name="cart"),
path("checkout/",views.checkout,name="checkout"),
path("update_item/",views.updateItem,name="update_item"),
]
The Error seems to also occur in my fetch function in the JS file. With my method POST. Can't find a solution, what am I doing wrong here?
The main problem is that you are trying to access 'request.data', there is no such attribute. What you want is to retrieve data from the POST request.
(Also, note that good practice is to have your views and variable names in snake_case form, whereas camelCase is used for classes):
def updateItem(request):
data = json.loads(request.POST.get('data'))
...
return JsonResponse("Item was added!", safe=False)
Although, to complete my answer, I must say that I had problems with your JS function, with the csrf token not being properly attached. My test solution:
views.py
from django.shortcuts import render
from django.http import JsonResponse
import json
def update_item(request):
return render(request, 'update_item.html', {})
def update_item_ajax(request):
data = json.loads(request.POST.get('data'))
print(data)
...
return JsonResponse({'message': '"Item was added!"'}, safe=False)
# output of update_item_ajax print
{'productId': 1, 'action': 'myaction'}
urls.py
from django.urls import path
from core import views
app_name = 'core'
urlpatterns = [
path('update/item/', views.update_item, name='update-item'),
path('update/item/ajax/', views.update_item_ajax, name='update-item-ajax'),
]
update_item.html
{% extends 'base.html' %}
{% block content %}
<button onclick="updateUserOrder(1, 'action')"> update item </button>
{% endblock %}
{% block script %}
<script>
function updateUserOrder(productId, action) {
console.log('User is logged in...');
let url = "{% url 'core:update-item-ajax' %}";
var payload = {
productId: productId,
action: action
};
var data = new FormData();
data.append( 'data' , JSON.stringify( payload ) );
data.append('csrfmiddlewaretoken', '{{ csrf_token }}');
fetch(url,
{
method: 'POST',
body: data,
})
.then(function(res){ return res.json(); })
.then(function(data){ console.log(data); });
}
</script>
{% endblock %}
Try:
data = json.loads(request.body)
Because the request doesn't have data, since you pass the data as body: JSON.stringify({ productId: productId, action: action }),
Using jsondump in python I need to send response to ajaxpage
object format in python shell show in below image
how to use the Java server object notation function to send response
//view output data
[<Userpost: Userpost object>, <Userpost: Userpost object>]
//this is my django view
def load_scroll_posts(request):
if request.method == 'POST':
post_id = request.POST['post_id']
loaded_posts = Userpost.objects.filter(id__gte = post_id)
return HttpResponse(json.dumps({'up':loaded_posts}))
//this is my ajax function
function load_remain_user_posts() {
var post_id = $(".message_box:last").attr("id");
var csrftoken = getCookie('csrftoken');
$.post('/theweber.in/load_m',{
post_id ':post_id,'
csrfmiddlewaretoken ':csrftoken},
function(data){
//console.log(data)
var obj = JSON.parse(data);
console.log(obj)
});
}
in console nothing displaying
Perhaps you mean to pass the two variables as parameters to your post? Something like:
function load_remain_user_posts() {
var post_id = $(".message_box:last").attr("id");
var csrftoken = getCookie('csrftoken');
var parameters = {
"post_id": post_id,
"csrfmiddlewaretoken": csrftoken
};
$.post('/theweber.in/load_m', parameters, function (data) {
//console.log(data)
var obj = JSON.parse(data);
console.log(obj)
});
}
I realised from my appengine log that the same cursor is being generated each time, the call to the Homehandler is made.
Please any idea what i am doing wrong, below is a snippet of my code:
class HomeHandler(webapp2.RequestHandler):
def get(self):
#page=self.request.get("page", default_value="1");
q = Allnews.query().order(-Allnews.date_added)
cursor = ndb.Cursor(urlsafe=self.request.get('cursor',default_value=None))
items, next_curs, more = q.fetch_page(30, start_cursor=cursor)
if more:
next_c = next_curs.urlsafe()
else:
next_c = None
context = { "news":items,"cursor":next_c}
# context["headlines"]=Feed.query(Feed.feed_cat.title == 'Headlines')
# context["gossip"] = Feed.query(Feed.feed_cat.title == 'Gossip')
# context["sports"] = Feed.query(Feed.feed_cat.title == 'Sports')
self.response.out.write(template.render('templates/homefeed.html',context))
this is the section of my homefeed.html template, I m using 'infinite scrolling' technique to fetch more results
<script>
{% if cursor %}
$(window).scroll(function()
{
var src=$("#src_val").val();
if($(window).scrollTop() == $(document).height() - $(window).height())
{
$('div#loadmoreajaxloader').show();
$.ajax({
url:"/home",
type:'GET',
data: {cursor: '{{cursor}}',feed_id:src },
success: function(news)
{
if(news)
{
$("#wrapper").append(news);
$('div#loadmoreajaxloader').hide();
}else
{
$('div#loadmoreajaxloader').html('No more posts to show.');
}
}
});
}
});
{% endif %}
</script>
It looks like you're using the get() method for both displaying a page and to handle an AJAX request. It's correctly generating a page with an initial cursor, but your $.ajax() method is expecting it to return JSON data.
Split the page request and AJAX request into two methods. Try adding a post() method to your HomeHandler that returns JSON data like this:
import json
def post(self):
q = Allnews.query().order(-Allnews.date_added)
cursor = ndb.Cursor(urlsafe=self.request.get('cursor',default_value=None))
items, next_curs, more = q.fetch_page(30, start_cursor=cursor)
if more:
next_c = next_curs.urlsafe()
else:
next_c = None
self.response.headers['Content-Type'] = 'application/json'
self.response.out.write(json.dumps({'news': items, 'cursor': next_c))
Now you have a method that returns JSON data to the AJAX request:
<script>
var cursor = null;
$(window).scroll(function()
{
if($(window).scrollTop() == $(document).height() - $(window).height())
{
$.ajax({
url:"/home",
type:'POST',
data: {cursor: cursor},
success: function(data)
{
$("#wrapper").append(data['news']);
cursor = data['cursor'];
if ( !cursor )
$('div#loadmoreajaxloader').show().html('No more posts to show.');
}
});
}
});
</script>
Notice how the cursor value is updated on each AJAX request. This is how you will get a new cursor on the next request.
(This code was not tested, you may need to debug it.)
form.html
<form action='/login/' method = 'post'>
{% csrf_token %}
<label>Email: (*)</label><input type='text' name='email' value='' /><br />
<label>Password: </label><input type='password' name='password' value='' /><br />
<input type='submit' name='submit' value='Log in' />
</form>
and views.py i use HttpResponse not render_to_response
def login(request):
success = False
message = ''
try:
emp = Employee.objects.get(email = request.POST['email'])
if emp.password == md5.new(request.POST['password']).hexdigest() :
emp.token = md5.new(request.POST['email'] + str(datetime.now().microsecond)).hexdigest()
emp.save()
info = serializers.serialize('json', Employee.objects.filter(email = request.POST['email']))
success = True
return HttpResponse(json.dumps({'success':str(success).lower(), 'info':info}))
else:
message = 'Password wrong!'
return HttpResponse(json.dumps({'success':str(success).lower(), 'message':message}), status = 401)
except:
message = 'Email not found!'
return HttpResponse(json.dumps({'success':str(success).lower(), 'message':message}), status = 401)
if use render_to_response, i just add RequestContext but HttpResponse, i don't know what to do.
i use Django 1.4
Where's my problem
=========================
My problem is sloved when I change the function that render the HTML :
def homepage(request):
return render_to_response('index.html')
to
def homepage(request):
return render_to_response('index.html', context_instance=RequestContext(request))
That's a stupid mistake... thanks...
If you are using ajax to send the form and have included jQuery, you have two possibilities:
Manually add the csrfmiddlewaretoken data to your POST request
Automate CSRF token handling by modifying jQuery ajax request headers
1. Manually add csrfmiddlewaretoken
var data = {
csrfmiddlewaretoken: $('#myForm input[name=csrfmiddlewaretoken]').val(),
foo: 'bar',
};
$.ajax({
type: 'POST',
url: 'url/to/ajax/',
data: data,
dataType: 'json',
success: function(result, textStatus, jqXHR) {
// do something with result
},
});
2. Automate CSRF token handling
jQuery(document).ajaxSend(function(event, xhr, settings) {
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;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
But: It is said that modifying the ajax request headers is bad practice. Therefore i'd go with solution number one.
Source: Cross Site Request Forgery protection: AJAX
The Django Documentations (CSRF DOC LINK) clearly explains how to enable it.
This should be the basic way of writing view with csrf token enabled..
from django.views.decorators.csrf import csrf_protect
#csrf_protect
def form(request):
if request.method == 'GET':
#your code
context = {}
return render (request, "page.html", context )
I've created a form and populating its value from Category model in drop down box. Its working.
I displayed this form in template like this {{ language_form }}.It worked. Now I want to implement onchange event on this drop down with ajax. Function will call on change of drop down value.
Edit:it can be done like this without django forms . <select onchange='ajaxfunction()'></select> But I'm using django forms.
Form
from django import forms
from myapp.movie.models import Category
class Language(forms.Form):
language = forms.ModelChoiceField(queryset=Category.objects.all())
Here is my Ajax function
function showMovie(str) {
if (str == "") {
document.getElementById("txtHint").innerHTML = "";
return;
}
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "movie_list?q=" + str, true);
xmlhttp.send();
}
If you want to just add onchange attr, then:
class Language(forms.Form):
language = forms.ModelChoiceField(queryset=Category.objects.all(), widget=forms.Select(attrs={'onchange':'ajaxfunction()'}))
Or you can render form manually.
Add this code in the end of your form.
...
</form>
<script type="text/javascript">
var ddl = document.getElementById('ddlYourDropDownListID');
ddl.onchange = function() {
var str = 'someValue';
showMovie(str);
};
</script>
</body>
</html>