Serving a django model containing objects - django

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.

Related

render() missing 1 required positional argument: 'data'

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

Custom validation is not working inside forms.py

I want to validate my email field like: if email contains [gmail.com,outlook.com,yahoo.com] then I want to raise validation Error. But it's not working, I don't know what i am doing wrong. plz help me
views.py
from django.shortcuts import render
from django.views.generic import View
from access.utils import is_valid
from access.mixin import HttpResponseMixin
import json
from access.forms import Employer_Form
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
#method_decorator(csrf_exempt,name = 'dispatch')
class Emp_Registration_view(View,HttpResponseMixin):
def post (self,request,*args,**kwargs):
data = request.body
json_data = is_valid(data)
if not json_data:
return self.render_http_response(json.dumps({'msg':'Please send valid json only'}),status=400)
emp_data = json.loads(data)
form= Employer_Form(emp_data)
if form.is_valid():
form.save(commit=True)
return self.render_http_response(json.dumps({'msg':'Registered Successfully'}))
if form.errors:
return self.render_http_response(json.dumps(form.errors),status=400)
forms.py
from access.models import Employer_Registration
from django import forms
class Employer_Form(forms.ModelForm):
def clean_email(self):
email = self.cleaned_data['emp_email']
email_lists = ['gmail.com','yahoo.com','outlook.com','hotmail.com']
data = emp_email.split('#')
if data in email_lists:
raise forms.ValidationError("email is not valid")
return email
class Meta:
model = Employer_Registration
fields = '__all__'
Your method should be named clean_emp_email, because the field is named emp_email. Otherwise it won't be called.
Seems like you are splitting on # so if you split example#gmail.com it will be [example , gmail.com] and that you are comparing in this line exactly
if [example , gmail.com] in email_lists
so it is not found I suggest you to do you can omit splitting and find in substring as
for i in email_lists:
if i in self.cleaned_data['emp_email']:
raise forms.ValidationError("email is not valid")
After #Alexandr Tatarinov answer you should also call the clean_field_name or simply clean

Displaying a raw image using CBVs in Django

I want to do some image manipulation, but before I do I want to render the image. This is what I've tried, but it does not work. The page is blank, no errors, why?
class ImgThumbnail(DetailView):
queryset = Images.objects.all()
def render_to_response(self, context, **response_kwargs):
from PIL import Image
import requests
from io import BytesIO
response = requests.get('http://example.com/media/images/{}.jpg'.format(self.pk))
img = Image.open(BytesIO(response.content))
return HttpResponse(img, content_type='image/jpg')
You should use StreamingHttpResponse. In a way like:
(dynamic content type and content length as bonus)
try:
from cStringIO import StringIO
except ImportError:
from io import StringIO
from wsgiref.util import FileWrapper
from django.http import HttpResponse, StreamingHttpResponse
class ImgThumbnail(DetailView):
queryset = Images.objects.all()
def get(self, request, *args, **kwargs):
r = requests.get('http://example.com/media/images/{}.jpg'.format(self.pk))
if not r.status_code == 200:
return HttpResponse('', status=r.status_code)
wrapper = FileWrapper(StringIO(r.content))
response = StreamingHttpResponse(wrapper, content_type=r.headers.get('Content-Type'))
response['Content-Length'] = r.headers.get('Content-Length')
return response
DetailView doesn't have a render_to_response method, so there is no point in defining your own.
You're not using any of the functionality of DetailView here anyway. You should inherit from the base View class, and put your code in the get method.

Django get resource in Json

import json
from django.core import serializers
from django.http import HttpResponse, Http404
from menu.models import *
def Database(request):
if request.method == 'GET':
menus = Menu.objects.all()
return toJSON(serialize(menus))
def serialize(menus):
serialized = []
for obj in menus:
serialized.append(obj.serializer())
return serialized
def toJSON(menus, status=200):
j = json.dumps(menus, ensure_ascii=False)
return HttpResponse(j, status=status, content_type='application/json; charset=utf-8')
I make my views.py like this, but it returns just [], How can I solve this?
did you mean you don't get key-value pair, instead you get just list ?
use
j = json.dumps({"menus":menus}, ensure_ascii=False)
instead of
j = json.dumps(menus, ensure_ascii=False)

Override Django Object Serializer to get rid of specified model

I need to convert a Django Queryset Object into a Json string. The built in Django Serialization library works great. Although it specifies the name of the Model from where it was created. Since I don't need this, how do I get rid of it? What else do I need to override to be able to use the overridden end_object method below?
class Serializer(PythonSerializer):
def end_object(self, obj):
self.objects.append({
"model" : smart_unicode(obj._meta), # <-- I want to remove this
"pk" : smart_unicode(obj._get_pk_val(), strings_only=True),
"fields" : fields
})
self._current = None
Sorry I had totally forgot about this question. This is how I ended up solving it (with thanks to FunkyBob on #django):
from django.core.serializers.python import Serializer
class MySerialiser(Serializer):
def end_object( self, obj ):
self._current['id'] = obj._get_pk_val()
self.objects.append( self._current )
# views.py
serializer = MySerialiser()
data = serializer.serialize(some_qs)
Here's a serializer that removes all metadata (pk, models) from the serialized output, and moves the fields up to the top-level of each object. Tested in django 1.5
from django.core.serializers import json
class CleanSerializer(json.Serializer):
def get_dump_object(self, obj):
return self._current
Serializer = CleanSerializer
Edit:
In migrating my app to an older version of django (precipitated by a change in hosting provider), the above serializer stopped working. Below is a serializer that handles the referenced versions:
import logging
import django
from django.core.serializers import json
from django.utils.encoding import smart_unicode
class CleanSerializer148(json.Serializer):
def end_object(self, obj):
current = self._current
current.update({'pk': smart_unicode(obj._get_pk_val(),
strings_only=True)})
self.objects.append(current)
self._current = None
class CleanSerializer151(json.Serializer):
def get_dump_object(self, obj):
self._current['pk'] = obj.pk
return self._current
if django.get_version() == '1.4.8':
CleanSerializer = CleanSerializer148
else:
CleanSerializer = CleanSerializer151
Serializer = CleanSerializer
Override JSON serializer class:
from django.core.serializers.json import Serializer, DjangoJSONEncoder
from django.utils import simplejson
class MySerializer(Serializer):
"""
Convert QuerySets to JSONS, overrided to remove "model" from JSON
"""
def end_serialization(self):
# little hack
cleaned_objects = []
for obj in self.objects:
del obj['model']
cleaned_objects.append(obj)
simplejson.dump(cleaned_objects, self.stream, cls=DjangoJSONEncoder, **self.options)
In the view:
JSONSerializer = MySerializer
jS = JSONSerializer()