1

It's my first time with rest framework. I'm trying to serialize my home app.

File models.py:

class User(AbstractUser):
    """User model."""

    username = None
    email = models.EmailField(_('email address'), unique=True)
    location = map_fields.AddressField(max_length=200)
    preferred = models.ManyToManyField(Place, related_name='Preferred')
    disliked = models.ManyToManyField(Place, related_name='Disliked')
    maplocation = gis_models.PointField("longitude/latitude", geography=True, blank=False, null=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    @classmethod
    def make_preferred(cls, current_email, new_pref_place):
        user, created = cls.objects.get_or_create(
            email=current_email
        )
        user.preferred.add(new_pref_place)

    @classmethod
    def remove_preferred(cls, current_email, pref_place):
        user, created = cls.objects.get_or_create(
            email=current_email
        )
        user.preferred.remove(pref_)lace

    @classmethod
    def make_dislike(cls, current_email, dislike_place):
        user, created = cls.objects.get_or_create(
            email=current_email
        )
        user.disliked.add(dislike_place)

    @classmethod
    def remove_dislike(cls, current_email, dislike_place):
        user, created = cls.objects.get_or_create(
            email=current_email
        )
        user.disliked.remove(dislike_place)

class Place(models.Model):
    name = models.CharField(max_length=200)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="Unique ID for this particular place across whole library")
    email = models.EmailField(max_length=70,blank=False)
    city = models.CharField('city', blank=False, default='Rabat', max_length=200, null=False)
    place_pic = models.ImageField(upload_to = 'pic_folder/', default = 'http://placehold.it/150x150', null= True)
    location = gis_models.PointField("longitude/latitude", geography=True, blank=False, null=True)
    #objects = gis_models.GeoManager()

    def __unicode__(self):
        return self.name, 'location'

File views.py:

@login_required
@api_view(['GET', 'PUT', 'DELETE'])
def home(request, format=None):
"""
    View function for home page of site.
"""
place_list = Place.objects.all() # get all the places from db to place_list
user = User.objects.get(email=request.user) # get the email of the current user
preferred_list = user.preferred.all() #get all the preferred places for the current user
disliked_list = user.disliked.all() #get all the disliked places for the current user in disliked_list
ref_location = user.maplocation # get the coordinates of the user from maplocation to ref_location
place_order = Place.objects.annotate(distance=D('location', ref_location)).order_by('distance')     # Render the HTML template home.html with the data in the context variable
return Response({'place_list': PlaceSerializer(place_list,many=True).data}, {'place_order': PlaceSerializer(place_order,many=True).data}, {'disliked_list': PlaceSerializer(disliked_list,many=True).data}, {'preferred_list': PlaceSerializer(preferred_list,many=True).data},)


@login_required
@api_view(['GET', 'PUT', 'DELETE'])
def favorites(request, format=None):
"""
    View of the preferred plac list
"""
user = User.objects.get(email=request.user)
preferred_list = user.preferred.all()
return Response({'preferred_list': PlaceSerializer(preferred_list,many=True).data},
)

@login_required
@api_view(['GET', 'PUT', 'DELETE'])
def dislikes(request, format=None):
"""
    View of the disliked place list
"""
user = User.objects.get(email=request.user)
disliked_list = user.disliked.all()
return Response({'disliked_list': PlaceSerializer(disliked_list,many=True).data},
)


@api_view(['GET', 'PUT', 'DELETE'])
def change_preferred(request, operation, id):
"""
    add or remove place from preferred list of places
"""
place = Place.objects.get(id=id)
if operation == 'add':
    User.make_preferred(request.user, place)
    return redirect('home')
elif operation == 'remove':
    User.remove_preferred(request.user, place)
    return redirect('favorites')

@api_view(['GET', 'PUT', 'DELETE'])
def change_disliked(request, operation, id):
"""
add or remove place from disliked list of places
"""
place = Plac.objects.get(id=id)
if operation == 'add':
    User.make_dislike(request.user, place)
    return redirect('home')
elif operation == 'remove':
    User.remove_dislike(request.user, place)
    return redirect('home')


@api_view(['GET', 'POST'])
def signup(request):
  if request.method == 'POST':
    form = SignUpForm(request.POST)
    if form.is_valid():
        form.save()
        email = form.cleaned_data.get('email')
        raw_password = form.cleaned_data.get('password1')
        user = authenticate(email=email, password=raw_password)
        login(request, user)
        return redirect('/city_places')
else:
    form = SignUpForm()
return Response(request, 'signup.html', {'form': UserSerializer(form,many=True).data})

File serializers.py:

from rest_framework import serializers
from .models import Shop, User
from rest_framework_gis.serializers import GeoFeatureModelSerializer
from .views import *

class ShopSerializer(serializers.ModelSerializer):
    geo_field = "location"
    class Meta:
        model = Shop
        fields = ('location' ,'name', 'shop_pic')


 class UserSerializer(serializers.ModelSerializer):
    id = serializers.UUIDField(format='hex_verbose')
    geo_field = "maplocation"
    class Meta:
        model = User
        fields =  '__all__'

I have a liste of places in the city and want to display them to the user and I do a query to order them by distance and display them in the home page, when I'm trying to serialize this I get this error:

Internal Server Error: /api/
Traceback (most recent call last):
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/core/handlers/base.py", line 158, in _get_response
response = self.process_exception_by_middleware(e, request)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/core/handlers/base.py", line 156, in _get_response
response = response.render()
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/template/response.py", line 106, in render
self.content = self.rendered_content
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/response.py", line 72, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/renderers.py", line 105, in render
allow_nan=not self.strict, separators=separators
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/utils/json.py", line 28, in dumps
return json.dumps(*args, **kwargs)
File "/usr/lib/python3.5/json/__init__.py", line 237, in dumps
**kw).encode(obj)
File "/usr/lib/python3.5/json/encoder.py", line 198, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.5/json/encoder.py", line 256, in iterencode
return _iterencode(o, 0)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/utils/encoders.py", line 68, in default
return super(JSONEncoder, self).default(obj)
File "/usr/lib/python3.5/json/encoder.py", line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <Place: Place object (3773482c-862d-4cc3-b2dd-8967e00cd730)> is not JSON serializable
[18/Apr/2018 11:49:11] "GET /api/?format=json HTTP/1.1" 500 129970

I don't know if it's the best way to do this, but I'm trying to get a favorite liste of place and a kind of black list of this places.

edit question after using @Jerin Peter George response I get this error about http status code must be an integer,

Internal Server Error: /api/
Traceback (most recent call last):
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/http/response.py", line 49, in __init__
self.status_code = int(status)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'dict'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/views.py", line 494, in dispatch
response = self.handle_exception(exc)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/views.py", line 454, in handle_exception
self.raise_uncaught_exception(exc)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/views.py", line 491, in dispatch
response = handler(request, *args, **kwargs)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/decorators.py", line 53, in handler
return func(*args, **kwargs)
File "~/Projects/Places/city_Place/views.py", line 38, in home
return Response({'place_list': PlaceSerializer(place_list,many=True).data}, {'place_order': PlaceSerializer(place_order,many=True).data}, {'disliked_list': PlaceSerializer(disliked_list,many=True).data}, {'preferred_list': PlaceSerializer(preferred_list,many=True).data},)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/rest_framework/response.py", line 32, in __init__
super(Response, self).__init__(None, status=status)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/template/response.py", line 36, in __init__
super().__init__('', content_type, status, charset=charset)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/http/response.py", line 283, in __init__
super().__init__(*args, **kwargs)
File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/http/response.py", line 51, in __init__
raise TypeError('HTTP status code must be an integer.')
TypeError: HTTP status code must be an integer.
[19/Apr/2018 04:05:36] "GET /api/ HTTP/1.1" 500 168031
E.Mohammed
  • 163
  • 1
  • 4
  • 13
  • looks like a typo `Place.id = serializers.UUIDField(format='hex_verbose')` to `id = serializers.UUIDField(format='hex_verbose')`? – Brown Bear Apr 18 '18 at 11:09
  • Possible duplicate of [ is not JSON serializable](https://stackoverflow.com/questions/16790375/django-object-is-not-json-serializable) – cwallenpoole Apr 18 '18 at 11:56
  • @BearBrown I tried this in the first time, but it gives me the same error, – E.Mohammed Apr 18 '18 at 12:28
  • @cwallenpoole, could you pleas give me more explanations about how to do the same way for my view, I have more than one object to return. so how can I do that. Thanks – E.Mohammed Apr 18 '18 at 12:31
  • @E.Mohammed You really need to show your troubleshooting steps *after* incorporating that information. – cwallenpoole Apr 18 '18 at 12:32
  • @cwallenpoole, I added to my views.py, place_order['id'] = model_to_dict(place_order['id']) preferred_list[''] = model_to_dict(preferred_list['']) disliked_list[''] = model_to_dict(disliked_list['']) return HttpResponse(json(preferred_list, disliked_list, place_order) ) I get the same errors, File "~/Projects/Place/city_places/views.py", line 39, in home place_order['id'] = model_to_dict(place_order['id']) File "~/.virtualenvs/my_django_environment/lib/python3.5/site-packages/django/db/models/query.py", line 282, in __getitem__ raise TypeError TypeError – E.Mohammed Apr 18 '18 at 13:20

1 Answers1

0

this line in home() causing the exception,

return Response({'place_list': place_list,
                 'preferred_list': preferred_list,
                 'disliked_list': disliked_list,
                 'place_order': place_order, })


In this statement, you are passing Place instances/queryset to the response, which is not JSON Serializable. So What you have to do is, serialize the queryset before returning.

example,
Replace the above statement with following,

return Response({'place_list': PlaceSerializer(place_list,many=True).data})
JPG
  • 82,442
  • 19
  • 127
  • 206
  • thank you, I think it solved the problem, but I have a new error type, raise TypeError('HTTP status code must be an integer.') TypeError: HTTP status code must be an integer. – E.Mohammed Apr 18 '18 at 21:42
  • it means, somewhere you are providing a **non-integer value** for `HTTP Status code` – JPG Apr 19 '18 at 01:19
  • yes, I'm confused about that, I think the **Respond** module need that I add the exception cases when the instance/queryset is empty and specify a code error for this case . – E.Mohammed Apr 19 '18 at 01:50
  • It's not about something in queryset. You provided some `str` type vaule insted of `int` type – JPG Apr 19 '18 at 01:53
  • Thank you, I can't find where the problem is exactly. the fields that are integer could be the geo_field and the id and both are defined in the serializer class as you can see in my code. – E.Mohammed Apr 19 '18 at 02:24
  • return Response({'place_list': PlaceSerializer(place_list,many=True).data}, {'place_order': PlaceSerializer(place_order,many=True).data}, {'disliked_list': PlaceSerializer(disliked_list,many=True).data}, {'preferred_list': PlaceSerializer(preferred_list,many=True).data},) – E.Mohammed Apr 19 '18 at 02:27
  • I had to use a single dictionary for that I used a bad syntaxe. this issue is solved here, [HTTP status code must be an intege](https://stackoverflow.com/questions/49926710/error-http-status-code-must-be-an-integer/49926817#49926817) – E.Mohammed Apr 19 '18 at 18:38