Error occurs while calling render function
If you aim on returning a JSON response try using a JsonResponse object as stated in the official docs
Example code:
from django.http import JsonResponse
from django.core import serializers
def student_detail(request):
obj = Student.objects.get(id=2)
json_data = serializers.serialize('json', [obj, ]) # serialize method needs an iterator
return JsonResponse(json_data, safe=False)
Try this:
json_data = JSONRenderer().render(serializer.data)
first of all you have to create your render; render = JSONRenderer() and then use method with passing argument data render.render(data=data) where data is NameOfYourSerializer.data
Related
I'm trying to pass 2 arrays via ajax from my views to my javascript. When I console.log my arrays i get 2 empty ones. I feel like I know what the error is but I can't solve it. I'm going to include my code first, than my toughts.
views.py:
In my first method, I want to pass my data to 2 arrays (dates,weights). In get_data is where I want to send my data to js.
from django.shortcuts import render
from django.contrib import messages
from django.contrib.auth.models import User
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from users import models
from users.models import Profile
from .forms import WeightForm
import json
dates = []
weights = []
dates_queryset = []
def home(request):
form = WeightForm()
if request.is_ajax():
profile = get_object_or_404(Profile, id = request.user.id)
form = WeightForm(request.POST, instance=profile)
if form.is_valid():
form.save()
return JsonResponse({
'msg': 'Success'
})
dates_queryset = Profile.objects.filter(user=request.user)
dates = dates_queryset.values_list('date', flat=True)
weights = dates_queryset.values_list('weight', flat=True)
return render(request, 'Landing/index.html',{'form':form})
def get_data(request, *args,**kwargs):
data = {
'date': dates,
'weight': weights
}
return JsonResponse(data)
url:
url(r'^api/data/$', get_data, name='api-data'),
Ajax call:
var endpont = '/api/data'
$.ajax({
method: 'GET',
url: endpont,
success: function(data){
console.log(data);
},
error: function(error_data){
console.log("Error");
console.log(error_data);
}
})
Js console.log output:
{date: Array(0), weight: Array(0)}
My toughts:
I think I need to pass both of my arrays to the context, but if I try to pass them like this {'form':form, 'dates':dates, 'weights':weights'} then I get an error that they are referenced before use. I saw another question on Stackoverflow where they put more than 1 value to the context like this.
Your get_data view is doing exactly what it is supposed to.
You've defined the dates and weights arrays in the global scope, and the home view is not changing those global variables, even though they are named the same thing. See this link for a simple demonstration. Python Global Variables
If you use the global keyword in front of "dates" and "weights" in the home view, then those variables would be updated, and get_data should return the populated arrays.
I have following django model:
class Weather(models.Model):
lat_lng = gis_models.PointField()
raw_data = psql_fields.JSONField(null=True)
I have following view:
def weather(request):
data = WeatherModel.objects.all()
js_data = serializers.serialize('json', data)
return HttpResponse(js_data, content_type='application/json')
It throws error saying 'Point object is not json serializable.'
I want this function to return json.
Please help.
The default JSON serializer doesn't know how to serialize Point objects.
Derive your own from Django's encoder. You can also use JsonResponse for shorter code:
from django.contrib.gis.geos import Point
from django.core.serializers.json import DjangoJSONEncoder
from django.http import JsonResponse
class GeoJSONEncoder(DjangoJSONEncoder):
def default(self, obj):
if isinstance(obj, Point):
return obj.coords
return super().default(obj)
def weather(request):
data = WeatherModel.objects.all()
return JsonResponse(data, encoder=GeoJSONEncoder)
You can use JsonResponse with values.
from django.http import JsonResponse
def weather(request):
data = list(WeatherModel.objects.all())
js_data = serializers.serialize('json', data)
return JsonResponse(data, safe=False) # or JsonResponse({'data': data})
Modifed answer from here.
I am trying to use REST API in django for retrieve some data in json format.
When i hit this url:
http://192.168.2.87:8000/locker/123/
It gives me output like this (from Database)
{"id": 1, "locker_id": 123, "locker_user_name": "taimur"}
But if i want to get the output by passing the parameters like this
http://192.168.2.87:8000/locker/?locker_id=123&locker_user_name=taimur&id=1
views.py
from postman, How can i do this??
from django.shortcuts import render, HttpResponse, get_object_or_404
from django.http import JsonResponse
from .models import Locker
from .serializers import LockerSerializer
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
def locker_data_response(request, locker_id):
if request.method == 'GET':
locker_information = get_object_or_404(Locker, locker_id = locker_id)
print(locker_information)
locker_information_serialize = LockerSerializer(locker_information)
print(locker_information_serialize)
return JsonResponse(locker_information_serialize.data)
urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
re_path('(?P<locker_id>[0-9]+)/$', views.locker_data_response, name='locker_data_response'),
]
You get them from the request object:
def locker_data_response(request):
if request.method == 'GET':
locker_id = request.data.get('locker_id') # this will return None if not found
locker_user_name = request.data.get('locker_user_name')
locker_information = get_object_or_404(Locker, locker_id=locker_id)
print(locker_information)
locker_information_serialize = LockerSerializer(locker_information)
print(locker_information_serialize)
return JsonResponse(locker_information_serialize.data)
And the url will change to:
locker/$
[EDIT: Sorry, if you are using drf you should use data rather than GET]
[EDIT 2: If you want to use it like this, you will also need to change the url and signature of the view]
[EDIT 3: Added the code in the correct place in view]
If your url is something like domain/search/?q=haha, Then you would use request.GET.get('q', '').
q is the parameter you want, And '' is the default value if q isn't found.
If you are instead just configuring your URLconf, Then your captures from the regex are passed to the function as arguments (or named arguments).
Such as:
(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),
Then in your views.py you would have
def profile_page(request, username):
# Rest of the method
Lets say I have this APIView
class Dummy(APIView):
def get(self, request):
return Response(data=request.query_params.get('uuid'))
To test it, I need to create a request object to pass into the get function
def test_dummy(self):
from rest_framework.test import APIRequestFactory
factory = APIRequestFactory()
request = factory.get('/?uuid=abcd')
DummyView().get(request)
It complains about AttributeError: 'WSGIRequest' object has no attribute 'query_params'
Having a closer look, the factory creates a WSGIRequest instance instead of a DRF version <class 'rest_framework.request.Request'>.
>>> from rest_framework.test import APIRequestFactory
>>> factory = APIRequestFactory()
>>> request = factory.get('/')
>>> request.__class__
<class 'django.core.handlers.wsgi.WSGIRequest'>
Refer to Tom's solution, DummyView()(request) will raise error:
TypeError: 'DummyView' object is not callable
Instead, should use as_view just like what you do in urls.py:
DummyView.as_view()(request)
DRF's as_view uses method initialize_request to convert Django Request object to DRF version. You can try with:
from rest_framework.views import APIView
APIView().initialize_request(request)
>>> <rest_framework.request.Request object at 0xad9850c>
You can also use APIClient to run test. It also tests URL dispatching.
from rest_framework.test import APIClient
client = APIClient()
client.post('/notes/', {'title': 'new idea'}, format='json')
That's right. At the moment APIRequestFactory returns an HttpRequest object, which only get upgraded to a REST framework Request object once it gets to the view layer.
This mirrors the behavior that you'll see in an actual request, and what it does do is deal with eg. rendering JSON, XML or whatever other content type you have configured for your test requests.
However I agree that it's surprising behavior and at some point it will probably return a Request object, and the REST framework view will ensure that it only performs the Request upgrade on requests that instances of HttpRequest.
What you need to do in your case is actually call the view, rather than invoking the .get() method...
factory = APIRequestFactory()
request = factory.get('/?uuid=abcd')
view = DummyView.as_view()
response = view(request) # Calling the view, not calling `.get()`
I realize this answer is some time after the question was asked, but it solved this issue for me. Just override the APIRequestFactory class as below.
# Override APIRequestFactory to add the query_params attribute.
class MyAPIRequestFactory(APIRequestFactory):
def generic(self, method, path, data='',
content_type='application/octet-stream', secure=False,
**extra):
# Include the CONTENT_TYPE, regardless of whether or not data is empty.
if content_type is not None:
extra['CONTENT_TYPE'] = str(content_type)
request = super(MyAPIRequestFactory, self).generic(
method, path, data, content_type, secure, **extra)
request.query_params = request.GET
return request
This is my code:
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django import http
from django.http import HttpResponse
def main(request, template_name='index.html'):
HttpResponse.set_cookie('logged_in_status', 'zjm1126')
context ={
'a':a,
'cookie':HttpResponse.get_cookie('logged_in_status'),
}
return render_to_response(template_name, context)
#return http.HttpResponsePermanentRedirect(template_name)
It raises this exception:
unbound method set_cookie() must be called with HttpResponse instance as first argument (got str instance instead)
What can I do?
You can't just start calling methods on the HttpResponse class, you have to instantiate it e.g. response = HttpResponse("Hello World"), call the cookie method, and then return it from your view.
response = render_to_response(template_name, context)
response.set_cookie('logged_in_status', 'never_use_this_ever')
return response
# remember my other answer:
# it's a terrrible idea to set logged in status on a cookie.
To get the cookie:
request.COOKIES.get('logged_in_status')
# remember, this is a terrible idea.
In case you want the raw cookie string (tested with Django 4.1)
request.META.get('HTTP_COOKIE')