Handling JsonResponse in Django template - python

I'm trying to make a webpage in which you can specify a number of vectors, then insert modulus and angle for each one, and it will calculate the sum.
My code can do the calculation, but I can't properly display the result on my template.
views.py:
def sum_view(request):
if request.method == "POST":
message = ''
for j in range(2,12):
if not request.POST.get(f'vector_mod_{j}'):
num_vett = j - 1
result = Vector(0, 0)
for i in range(num_vett):
mod = float(request.POST.get(f'vector_mod_{i+1}'))
ang = float(request.POST.get(f'vector_ang_{i+1}'))
result += Vector(mod, ang)
message = f'Modulus: {result.modulus}, angle: {result.angle}°'
return JsonResponse({'message': message})
return render(request, 'vectsum/sum.html')
The problem is that when I submit I see a sort of firefox developer tools view with a menu including 'JSON', 'Raw Data', 'Headers', and the correct message displayed in a console-like way.
Here is the ajax part of my template:
$(document).on('submit','#calculate',function(e){
e.preventDefault();
$.ajax({
type:'POST',
headers: {'X-Requested-With': 'XMLHttpRequest'},
url:'/vectorialsum/',
data: $('#calculate').serialize()
success:function(data){
var mess = JSON.parse(data)['message']
document.getElementById('result').innerHTML += mess
}
})
});
Probably I don't get what return JsonResponse does, however how do I show the message in my page?
Edit:
maybe my question is not clear, I'll rephrase: how can I send back to ajax's success function the message variable?

Related

Django Redirect does not work at all within view

I am trying to get my view to redirect to another page after clicking a button that triggers the POST request. I cannot seem to figure out why the redirect doesn't work or why it doesn't even seem to try to redirect.
Here is my view:
def cart1(request):
if request.user.is_authenticated:
#POST
if request.method == "POST":
#JSON Data
data = request.body
new_data = ast.literal_eval(data.decode('utf-8'))
customer = request.user
user_order = Order(user=customer)
user_order.save()
x = 0
while x < len(new_data.keys()):
obj_title = new_data[x]["title"]
obj_price = new_data[x]["price"]
obj_quantity = new_data[x]["quantity"]
obj_extra = new_data[x]["extra"]
total = round(float(obj_price.replace("$", "")))
m = OrderItem(order=user_order, title=obj_title, price=total, quantity=obj_quantity, extra=obj_extra)
m.save()
x += 1
return redirect('checkout-page')
return render(request, 'cart.html')
Any help would be appreciated, thank you
redirect(…) [Django-doc] produces a HttpRedirectResponse, you need to return it, so:
return redirect('checkout-page')
redirect(…) itself thus does not stop the code flow to redirect return a HTTP redirect response, it constructs such response, and your view should then return that response.
you need to be sure the URL name =checkout-page is in the current app otherwise you need to make it redirect('app:checkout-page')
However,I suggest to use from django.http import HttpResponseRedirect

Django multiple AJAX queries for images

I made a button the user can click and it makes a AJAX GET request to the backend class Image. The response is the image url. I paste the url into a image tag and display it on the template
models.py
class Image(models.Model):
img = models.ImageField()
views.py
def ajax(request):
from django.http import JsonResponse
if request.is_ajax():
image = request.FILES.get('data')
aaa = Image.objects.get(id=1)
aaa = str(aaa.img.url)
return JsonResponse({'image_query': aaa}, status=200)
return render(request, 'components/ajax.html')
AJAX (template)
<button id="getData" class="btn btn-success">Get</button>
<div id="seconds"></div>
...
<script>
$(document).ready(function () {
$('#getData').click(function () {
$.ajax({
url: 'ajax',
type: 'get',
data: {
data: $(this).text()
},
success: function (response) {
$('#seconds').append('<img src="' + response.image_query + '" width="300">')
}
})
})
})
</script>
Everything works fine and the image is rendered to the template! Now I dont want to query the image with ID=1, I want all images to be fetched to the template.
I tried to do by adding a for loop into the views.py but it only returns the first element.
if request.is_ajax():
image = request.FILES.get('data')
for i in range(1, 5):
aaa = Image.objects.get(id=i)
aaa = str(aaa.img.url)
return JsonResponse({'image_query': aaa}, status=200)
I don't know what to modify that it will query every image in the DB. Does someone have a solution for my problem?
It's returning the only first element because you are returning inside the for loop, instead put the return 1 indent back, and put all of the urls in array.
... # code you have above
images = []
for i in range(1, 5):
aaa = Image.objects.get(id=i)
images.append(aaa.img.url)) # append the url to the list
return JsonResponse({'images': images}, status=200) # 1 indent back
as a result you'll have to change your javascript code like this.
const success = (response) => {
// Loop through each of the links
for (let i=0; i < response.image_query.length; i++) {
$('#seconds').append('<img src="' + response.image_query[i] + '" width="300">')
}
}
// ... Other code
$.ajax({
url: 'ajax',
type: 'get',
data: {
data: $(this).text()
},
success: success,
});
Also be carefull with $('#seconds').append('<img src="' + response.image_query + '" width="300">'), appending raw html could cause an XSS attack, if you are not completely sure that response.image_query is safe do not do this. (Since it is a url it should be escaped)

How to get only json value using jquery from calling an API?

The API returns both JSON and also render the template and when i call $.getJSON it will only return that render template but not JSON value. I have tried this
if request.args['type'] == 'json':
return json.dumps(group)
else:
return render_template("/c.., summary=json.dumps(group))
but it says
bad request
Is there any way I can get that JSON value whenever I need it?
This is my view
#cms.route('/add/asset/<client_id>', methods=["GET"])
#login_required
def asset_add(client_id):
if int(current_user.id_) == int(client_id):
group = {}
group['id'] = []
group['pid'] = []
group['name'] = []
for index in range(len([r.id_ for r in db.session.query(Assetgroup.id_)])):
for asset in (Assetgroup.query.filter_by(parent_id=(index or ''))):
group['id'].append(asset.id_)
group['pid'].append(asset.parent_id)
group['name'].append(asset.name)
if request.args['type'] == 'json':
return json.dumps(group)
else:
return render_template("/cms/asset_add.html", action="/add/asset", asset=None,
client_id=client_id,
types=Type.query.all())
else:
return 'permission denied'
and this is my ajax request
$(document).ready(function () {
$('#group_id').click(function () {
$.getJSON(
'/add/asset/' + {{ client_id }},
function (data) {
$('#group_id').find('option').remove();
var len = data.id.length;
for (var i = 0; i < len; i++) {
var option_item = '<option value="' + data.id[i] + '">' + data.name[i] + "</option>";
$('#group_id').append(option_item);
}
}
);
});
});
You can add parameter in html call to get the json result...
i.e)
const Endpoint = '/add/asset/?'
$.getJSON(Endpoint, {type: 'json'}).done(function(data...)
I believe this is what you are looking for
http://flask.pocoo.org/docs/0.12/api/#flask.Request.is_json
That is a flask method that checks if the request is json
Then you can use jsonify still in flask to return json (you need to import it though)
from flask import jsonify
so your code becomes
if request.is_json:
return jsonify(group)
Hope you find that useful and more elegant
One of the easier ways to debug is just return json alone for a start to see how the response looks in a browser. So you can remove login required (assuming you are not yet in production), do not check if the request is_json, then call the api and see what it returns. So assuming your client id is 1
#cms.route('/add/asset/<client_id>', methods=["GET"])
def asset_add(client_id):
if int(current_user.id_) == int(client_id):
group = {}
group['id'] = []
group['pid'] = []
group['name'] = []
for index in range(len([r.id_ for r in db.session.query(Assetgroup.id_)])):
for asset in (Assetgroup.query.filter_by(parent_id=(index or ''))):
group['id'].append(asset.id_)
group['pid'].append(asset.parent_id)
group['name'].append(asset.name)
return jsonify(group)
Now you can visit http://yoursite.com/add/asset/1 to see your response

AJAX - Django - better approach?

I am pretty sure, i am messing up this.
I do ajax request to get some informations of an object.
$.ajax({
url: "/get_obj_ajax/",
type: "get",
data: {id:id}
}).done(function(data){
if(data!='bad'){
data = data.split('°');
var objtitle = data[0];
var objcontent = data[1];
..
});
and in django views:
def get_obj_ajax(request):
if request.method == "GET":
obj= MyModel.objects.get(id=int(request.GET.get('id')))
data = obj.title + '°' + obj.content
return HttpResponse(data)
return HttpResponse('bad')
this is what I normally do. but today while I was eating my lunch, I thought, there must be some more professional approach for this.. because i feel like this is too dumb code. and if suddenly content of my obj has something with ° in it, the parsing goes wrong.
.. any guidance will be appreciated.
you can return json data:
def get_obj_ajax(request):
import json
data={"issuccess": 'no'}
if request.method == "GET":
obj= MyModel.objects.get(id=int(request.GET.get('id')))
data = {"issuccess": 'yes',"title":obj.title ,"content": obj.content}
return HttpResponse(json.dumps(data), content_type="application/json")
in templates:
if(data.issuccess == 'yes'){
var objtitle = data.title;
var objcontent = data.content;
}...

Pass arguments to multiple forms with the same request in Django

I am new in django and I have a doubt:
Is possible pass arguments to a several forms.
Scenario:
I have an html table rendered with django-tables2, in the first column I have a drop down button. One item from the drop down button open a bootstrap modal window with 3 diffetent forms(all the forma re modelbased forms).
The arguments are pased with a javascript function, the function take the value from some cells of the html table and send this value as argument.
All this form take the same arguments. I can pass the arguments to one form but I need to pass the arguments to all the forms.
In simple words:
How can I pass arguments to various forms in the same post request?
How I say above I am new with django and I don't know if is possible get this functionality.
UPDATE
my forms: (all the forms have the same code. nonly the name change)
class RecepcionForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
super(RecepcionForm,self).__init__(*args,**kwargs)
self.helper = FormHelper(self)
self.helper.layout.append(Submit('save','Grabar'))
class Meta:
model = DetalleRecepcion
my views:(all the form use a view like this. only the name of the view change
def RecepcionView(request):
idp = request.GET.get('i')
anio = request.GET.get('a')
mes = request.GET.get('m')
if request.method == 'POST':
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
form = RecepcionForm(request.POST, instance=r)
if form.is_valid():
form.save()
return HttpResponseRedirect('/monitor/')
else:
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
form = RecepcionForm(instance=r)
return render_to_response('recepcion.html',
{'form':form},
context_instance=RequestContext(request))
I only know how to pass the value to an unique form. I use this fucntion:
<script type="text/javascript">
function param(){
var tbl = document.getElementById("myTable");
var rows = tbl.rows;
var argu = "";
for (var i = 0; i < rows.length; i++){
rows[i].onclick = function(){
idpro = this.cells;
argu = "?i="+idpro[0].innerHTML+"&a="+idpro[1].innerHTML+"&m="+idpro[2].innerHTML;
window.location = "/recepcion/"+argu;
}
}
}
</script>
I know that function is really bad coding, but I have some trouble to redirect toe the template using ajax post request.
I try to use this function but I can never redirect to the form where i send the parameters
<script type="text/javascript">
function param(){
$(function(){
//var http = new XMLHttpRequest();
var tbl = document.getElementById("myTable");
var rows = tbl.rows;
var url = "/recepcion/";
for (var i = 0; i < rows.length; i++){
rows[i].onclick = function(){
idpro = this.cells;
ano = this.cells;
mes1 = this.cells;
$.ajax({
async : false,
type:"GET",
url: "/recepcion/",
datatype: 'json',
data: ({i: idpro[0].innerHTML, a: ano[1].innerHTML, m: mes1[2].innerHTML }),
success: function(){
}
});
}
}
});
return false;
}
</script>
Any idea or advice how can I achieve this functionality.?
Thanks in advance

Categories