I'm trying to convert a server side Ajax response script into a Django HttpResponse, but apparently it's not working.
This is the server-side script:
/* RECEIVE VALUE */
$validateValue=$_POST['validateValue'];
$validateId=$_POST['validateId'];
$validateError=$_POST['validateError'];
/* RETURN VALUE */
$arrayToJs = array();
$arrayToJs[0] = $validateId;
$arrayToJs[1] = $validateError;
if($validateValue =="Testuser"){ // Validate??
$arrayToJs[2] = "true"; // RETURN TRUE
echo '{"jsonValidateReturn":'.json_encode($arrayToJs).'}'; // RETURN ARRAY WITH success
}
else{
for($x=0;$x<1000000;$x++){
if($x == 990000){
$arrayToJs[2] = "false";
echo '{"jsonValidateReturn":'.json_encode($arrayToJs).'}'; // RETURNS ARRAY WITH ERROR.
}
}
}
And this is the converted code
def validate_user(request):
if request.method == 'POST':
vld_value = request.POST.get('validateValue')
vld_id = request.POST.get('validateId')
vld_error = request.POST.get('validateError')
array_to_js = [vld_id, vld_error, False]
if vld_value == "TestUser":
array_to_js[2] = True
x = simplejson.dumps(array_to_js)
return HttpResponse(x)
else:
array_to_js[2] = False
x = simplejson.dumps(array_to_js)
error = 'Error'
return render_to_response('index.html',{'error':error},context_instance=RequestContext(request))
return render_to_response('index.html',context_instance=RequestContext(request))
I'm using simplejson to encode the Python list (so it will return a JSON array). I couldn't figure out the problem yet. But I think that I did something wrong about the 'echo'.
I usually use a dictionary, not a list to return JSON content.
import json
from django.http import HttpResponse
response_data = {}
response_data['result'] = 'error'
response_data['message'] = 'Some error message'
Pre-Django 1.7 you'd return it like this:
return HttpResponse(json.dumps(response_data), content_type="application/json")
For Django 1.7+, use JsonResponse as shown in this SO answer like so :
from django.http import JsonResponse
return JsonResponse({'foo':'bar'})
New in django 1.7
you could use JsonResponse objects.
from the docs:
from django.http import JsonResponse
return JsonResponse({'foo':'bar'})
I use this, it works fine.
from django.utils import simplejson
from django.http import HttpResponse
def some_view(request):
to_json = {
"key1": "value1",
"key2": "value2"
}
return HttpResponse(simplejson.dumps(to_json), mimetype='application/json')
Alternative:
from django.utils import simplejson
class JsonResponse(HttpResponse):
"""
JSON response
"""
def __init__(self, content, mimetype='application/json', status=None, content_type=None):
super(JsonResponse, self).__init__(
content=simplejson.dumps(content),
mimetype=mimetype,
status=status,
content_type=content_type,
)
In Django 1.7 JsonResponse objects have been added to the Django framework itself which makes this task even easier:
from django.http import JsonResponse
def some_view(request):
return JsonResponse({"key": "value"})
Since Django 1.7 you have a standard JsonResponse that's exactly what you need:
from django.http import JsonResponse
...
return JsonResponse(array_to_js, safe=False)
You don't even need to json.dump your array.
With Django Class-based views you can write:
from django.views import View
from django.http import JsonResponse
class JsonView(View):
def get(self, request):
return JsonResponse({'some': 'data'})
and with Django-Rest-Framework you can write:
from rest_framework.views import APIView
from rest_framework.response import Response
class JsonView(APIView):
def get(self, request):
return Response({'some': 'data'})
For those who use Django 1.7+
from django.http import JsonResponse
def your_view(request):
json_object = {'key': "value"}
return JsonResponse(json_object)
official docs
from django.http import HttpResponse
import json
class JsonResponse(HttpResponse):
def __init__(self, content={}, mimetype=None, status=None,
content_type='application/json'):
super(JsonResponse, self).__init__(json.dumps(content), mimetype=mimetype,
status=status, content_type=content_type)
And in the view:
resp_data = {'my_key': 'my value',}
return JsonResponse(resp_data)
You'll want to use the django serializer to help with unicode stuff:
from django.core import serializers
json_serializer = serializers.get_serializer("json")()
response = json_serializer.serialize(list, ensure_ascii=False, indent=2, use_natural_keys=True)
return HttpResponse(response, mimetype="application/json")
Its very convenient with Django version 1.7 or higher as you have the JsonResponse class, which is a subclass of HttpResponse.
from django.http import JsonResponse
def profile(request):
data = {
'name': 'Raghav',
'location': 'India',
'is_active': False,
'count': 28
}
return JsonResponse(data)
For older versions of Django, you must use an HttpResponse object.
import json
from django.http import HttpResponse
def profile(request):
data = {
'name': 'Raghav',
'location': 'India',
'is_active': False,
'count': 28
}
dump = json.dumps(data)
return HttpResponse(dump, content_type='application/json')
How to use google app engine with ajax (json)?
Code Javascript with JQuery:
$.ajax({
url: '/ajax',
dataType : 'json',
cache: false,
success: function(data) {
alert('Load was performed.'+data.ajax_resp);
}
});
Code Python
class Ajax(webapp2.RequestHandler):
def get(self):
my_response = {'ajax_resp':'Hello, webapp World!'}
datos = json.dumps(my_response)
self.response.headers.add_header('content-type', 'application/json', charset='utf-8')
self.response.out.write(datos)
First import this:
from django.http import HttpResponse
If you have the JSON already:
def your_method(request):
your_json = [{'key1': value, 'key2': value}]
return HttpResponse(your_json, 'application/json')
If you get the JSON from another HTTP request:
def your_method(request):
response = request.get('https://www.example.com/get/json')
return HttpResponse(response, 'application/json')
This is my preferred version using a class based view.
Simply subclass the basic View and override the get()-method.
import json
class MyJsonView(View):
def get(self, *args, **kwargs):
resp = {'my_key': 'my value',}
return HttpResponse(json.dumps(resp), mimetype="application/json" )
Django code views.py:
def view(request):
if request.method == 'POST':
print request.body
data = request.body
return HttpResponse(json.dumps(data))
HTML code view.html:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#mySelect").change(function(){
selected = $("#mySelect option:selected").text()
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
url: '/view/',
data: {
'fruit': selected
},
success: function(result) {
document.write(result)
}
});
});
});
</script>
</head>
<body>
<form>
{{data}}
<br>
Select your favorite fruit:
<select id="mySelect">
<option value="apple" selected >Select fruit</option>
<option value="apple">Apple</option>
<option value="orange">Orange</option>
<option value="pineapple">Pineapple</option>
<option value="banana">Banana</option>
</select>
</form>
</body>
</html>
Most of these answers are out of date. JsonResponse is not recommended because it escapes the characters, which is usually undesired. Here's what I use:
views.py (returns HTML)
from django.shortcuts import render
from django.core import serializers
def your_view(request):
data = serializers.serialize('json', YourModel.objects.all())
context = {"data":data}
return render(request, "your_view.html", context)
views.py (returns JSON)
from django.core import serializers
from django.http import HttpResponse
def your_view(request):
data = serializers.serialize('json', YourModel.objects.all())
return HttpResponse(data, content_type='application/json')
Bonus for Vue Users
If you want to bring your Django Queryset into Vue, you can do the following.
template.html
<div id="dataJson" style="display:none">
{{ data }}
</div>
<script>
let dataParsed = JSON.parse(document.getElementById('dataJson').textContent);
var app = new Vue({
el: '#app',
data: {
yourVariable: dataParsed,
},
})
</script>
This way the json contents can be downloaded as a file with a specific filename.
import json
from django.http import HttpResponse
def download_json(request):
data = {'some': 'information'}
# serialize data obj as a JSON stream
data = json.dumps(data)
response = HttpResponse(data, content_type='application/json charset=utf-8')
# add filename to response
response['Content-Disposition'] = 'attachment; filename="filename.json"'
return response
In View use this:
form.field.errors|striptags
for getting validation messages without html
def your_view(request):
response = {'key': "value"}
return JsonResponse(json.dumps(response), content_type="application/json",safe=False)
#Specify the content_type and use json.dump() son as the content not to be sent as object
Related
I have defined the following code in the views.py I am getting
TypeError : Object of type function is not JSON serializable
Libaries:
from django.db.models.query import QuerySet
from django.shortcuts import render
from django.http import HttpResponse , Http404 , JsonResponse
import json
from json import JSONEncoder
from FeedPost.models import trill
def home(request, *args, **kwargs):
return render(request, "feed.html", context={}, status=200)
Where the error occured
def trills_list_view(request, *args , **kwargs):
qs = trill.objects.all()
trills_list = [{"id": x.id, "name": x.name} for x in qs]
data = {
"response": trill_list
}
return JsonResponse(data)
def trill_list(request, trill_id, *args, **kwargs):
data = {
"id" : trill_id,
}
status = 200
try:
obj = trill.objects.get(id=trill_id)
data['name'] =obj.name
except:
data['message'] = "Not found"
status = 404
return JsonResponse(data, status=status)
i'm using an api to get informations about coronavirus cases around the world and i have an issue in the last line of code
from django.shortcuts import render
import requests
from django import forms
from django.views.generic import TemplateView
from .forms import homeform
def home(request):
if request.method =='POST':
form = homeform(request.POST)
if form.is_valid():
text = form.cleaned_data
field = text['name']
print(field)
country = field
else:
form = homeform()
country = 'algeria'
url = "https://covid-193.p.rapidapi.com/statistics"
querystring = {"country": country}
headers = {
'x-rapidapi-host': "covid-193.p.rapidapi.com",
'x-rapidapi-key': "36b864062emshac7e191eb5087e6p169e6bjsn24c86f3408c1"
}
response = requests.request("GET", url, headers=headers, params=querystring).json()
data = response['response']
print(data)
d = data[0]
context = {
'all': d['cases']['total'],
'recovered': d['cases']['recovered'],
'deaths': d['deaths']['total'],
'new': d['cases']['new'],
'serioz': d['cases']['critical'],
'active':d['cases']['active'],
'deaths_new':d['deaths']['new']
}
return render(request, 'index.html',{'form':form}, context)
here i have a problem with rendering the page it just shows my html code in the webpage but when i remove context from the last line of code evrything becomes normal , please help me
I think you are trying to pass two context dictionaries. Your {'form':form} is in the place of the context argument so your context isn't actually getting passed as a context. Add the form to the context dictionary in the line above return and remove {'form':form} from your render function.
I think you need to change your code to this :
return render(request, 'index.html',{'form':form,
'context':context})
This way you will get both in the html file.
I am trying my hands on File Upload using Django REST and Angular.
Following is the angular directory structure:
app
|-----uploadcomponent
|-----uploadcomponent.module.ts
|-----uploadcomponent.html
|-----app.module.ts
|-----app.component.ts
|-----app.service.ts
uploadcomponent.htl:
<div>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input type="file" name="profile" enctype="multipart/form-data" accept=".xlsm,application/msexcel" (change)="onChange($event)" />
<button type="submit">Upload Template</button>
<button id="delete_button" class="delete_button" type="reset"><i class="fa fa-trash"></i></button>
</form>
</div>
uploadcomponent.ts:
import { FormBuilder, FormGroup, ReactiveFormsModule } from '#angular/forms';
import { Component, OnInit } from '#angular/core';
....
export class UploadComponent implements OnInit {
form: FormGroup;
constructor(private formBuilder: FormBuilder, private uploadService: AppService) {}
ngOnInit() {
this.form = this.formBuilder.group({
profile: ['']
});
}
onChange(event) {
if (event.target.files.length > 0) {
const file = event.target.files[0];
this.form.get('profile').setValue(file);
console.log(this.form.get('profile').value)
}
}
onSubmit() {
const formData = new FormData();
formData.append('file', this.form.get('profile').value);
this.uploadService.upload(formData).subscribe(
(res) => {
this.response = res;
console.log(res);
},
(err) => {
console.log(err);
});
}
}
app.service.ts:
upload(formData) {
const endpoint = this.service_url+'upload/';
return this.http.post(endpoint, formData, httpOptions);
}
Now in the backend I am using Django Rest Framework:
Following are the required files of code:
models.py:
from __future__ import unicode_literals
from django.db import models
from django.db import connection
from django_mysql.models import JSONField, Model
import uuid
import os
def change_filename(instance, filename):
extension = filename.split('.')[-1]
file_name = os.path.splitext(filename)[0]
uuid_name = uuid.uuid4()
return file_name+"_"+str(uuid_name)+"."+extension
class UploadTemplate (Model):
id = models.AutoField(primary_key=True)
file = models.FileField(blank=False, null=False, upload_to=change_filename)
def __str__(self):
return str(self.file.name)
views.py:
class UploadView(APIView):
serializer_class = UploadSerializer
parser_class = (FileUploadParser,)
def get_queryset(self):
queryset = UploadTemplate.objects.all()
return queryset
def post(self, request, *args, **kwargs):
file_serializer = UploadSerializer(data=request.data)
status = None
message = None
if file_serializer.is_valid():
file_serializer.save()
status = "Success"
message = "Success"
else:
status = "Failure"
message = "Failure!"
content = {'status': status, 'message': message}
return Response(content)
serializers.py:
from uploadtemplate.models import UploadTemplate
from rest_framework import serializers
class UploadSerializer(serializers.ModelSerializer):
class Meta:
model = UploadTemplate
fields = '__all__'
urls.py:
router.register(r'uploadtemplate', uploadtemplateviews.UploadTemplateView, base_name='UploadTemplate')
urlpatterns = [
....
url(r'upload/', uploadtemplateviews.UploadTemplateView.as_view()),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Also I have made required changes in settings.py.
Now when I upload an excel sheet (.xlsm extension) through UI, I get the following error:
JSON parse error - 'utf-8' codec can't decode byte 0xc9 in position 213: invalid continuation byte
Now, when I try to read the same excel file using pandas, I can see that few of the column values are NaN and I doubt this might be the reason for decoding.
Can someone please help me out on how to handle this in Angular/Rest so that my file uploads successfully.
Thanks!
Got the answer for this...
In views.py I had to change the parser to:
parser_classes = [MultiPartParser]
So my views.py now looks like:
class UploadView(APIView):
serializer_class = UploadSerializer
parser_classes = [MultiPartParser] <<<<< Changes are here
def get_queryset(self):
queryset = UploadTemplate.objects.all()
return queryset
def post(self, request, *args, **kwargs):
file_serializer = UploadSerializer(data=request.data)
status = None
message = None
if file_serializer.is_valid():
file_serializer.save()
status = "Success"
message = "Success"
else:
status = "Failure"
message = "Failure!"
content = {'status': status, 'message': message}
return Response(content)
Also, the http request was sending Content-Type as application/json by default.
Had to change it. So my apps.service.ts looked as following:
upload(formData) {
const endpoint = this.service_url+'upload/';
const httpOptions = headers: new HttpHeaders({ <<<< Changes are here
'Authorization': 'token xxxxxxx'})
};
return this.http.post(endpoint, formData, httpOptions);
}
Thank You!
I want to retrieve data from the database when the bottom of the page is hit.
Now, what I have so far:
urls.py
urlpatterns = [
url(r'^$', feedViews.index, name='index'),
url(r'^load/$', feedViews.load, name='load'),
]
views.py
def index(request):
if request.method == 'GET':
context = {
'entry_list': Entry.objects.filter()[:5],
}
return render(request,'index.html',context)
else:
return HttpResponse("Request method is not a GET")
def load(request):
if request.method == 'GET':
context = {
'entry_list': Entry.objects.filter()[:1],
}
return render(request,'index.html',context)
else:
return HttpResponse("Request method is not a GET")
index.html
...
<script>
$(window).on("scroll", function() {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
console.log( "TEST" );
$.ajax(
{
type:"GET",
url: "/load",
data:{
},
})
}
});
</script>
...
Basicaly it loads 5 items at the beginning and what I try to achieve is that it loads 1 more as soon as I hit the bottom of the page.
So jQuery works beacuase the console.log('Test') works and in my terminal it says
"GET /load/ HTTP/1.1" 200 484
which is fine as well.
I think I messed up the ajax somehow. I am not sure though.
As you can probably tell I am a nooby but any help is highly appreciated.
Use something like this:
import json
from django.http import JsonResponse
def index(request):
if request.method == 'GET':
context = {
'entry_list': Entry.objects.filter()[:5],
}
return JsonResponse(json.dumps(context), safe=False)
else:
return JsonResponse({"err_msg": "Failed"})
Try it:
import json
from django.core import serializers
from django.http import JsonResponse
def index(request):
if request.method == 'GET' and request.is_ajax():
# Return objects
entry = Entry.objects.filter()[:5]
# serializers
entry2 = serializers.serialize('json', entry)
# convert JSON
entry3 = [d['fields'] for d in json.loads(entry2)]
data = dict()
data["entry"] = entry3
return JsonResponse(data)
I'm using the django_facebook library installed on pythonanywhere.
When I click a link from one view to another, I get an error message:
400 Bad Request
Missing signed_request.
Could someone give me the brief on how links work in a facebook app?
Removing the #canvas_only decorator doesn't solve the problem, because I need access to the graph api.
Here's the code:
views.py:
from django.shortcuts import render
from django_facebook.decorators import canvas_only
#from django_facebook.decorators import facebook_required
#from django.utils.decorators import method_decorator
from models import Poem, Share
from django import forms
from django.views.generic import View
class PoemEntryForm(forms.Form):
words = forms.CharField( widget=forms.widgets.Textarea(), initial='ENTER\nPOEM\nHERE\nONE\nWORD\nPER\nLINE' )
#canvas_only
def home(request):
me = request.facebook.graph.get_object('me')
my_username = me['username']
request.session['username'] = my_username
try:
poems = Poem.objects.filter(user=my_username)
except Poem.DoesNotExist:
poems = []
# convert poems into tuples of information relevant to the home page
# sort them in reverse chronological order
# ie: title and created
poems = [(poem.title(), poem.created) for poem in sorted(poems, key=lambda poem: poem.created, reverse=True)]
try:
shared = Share.objects.filter(shared_to=my_username)
except Share.DoesNotExist:
shared = []
shared = [(poem.title(), poem.user, poem.created) for poem in sorted(shared, key=lambda poem: poem.created, reverse=True)]
return render(request, 'home.html', {
'me': me,
'my_poems': poems,
'shared': shared,
})
class Create(View):
##method_decorator(canvas_only)
def get(self, request, *args, **kwargs):
#self.me = request.facebook.graph.get_object('me')
form = PoemEntryForm(request.GET)
return render(request, 'create.html', {
'form': form,
'debug': request.session['username']
})
##method_decorator(canvas_only)
def post(self, request, *args, **kwargs):
if request.session['username']:
form = PoemEntryForm(request.POST)
poem = Poem()
poem.user = request.session['username']
poem.text = request.POST['words']
poem.save()
return render(request, 'submitted.html', {})
else:
return render(request, 'error_submitting.html', {})
submitted.html:
<html>
<body>
<h3>You submitted a poem</h3>
Home
</body>
</html>
So the deal is this.
When the django, or whatever is doing the replying replies with: missing signed_request., what it really means is that the session doesn't contain an entry of key 'signed_request'. You can find this request in the POST data of the initial request. Save it in the session, and you're good to go.