Reputation: 3
When I tried to add value of language python3 returns error that this object is not JSON serializible.
models:
from django.db import models
from django.contrib.auth.models import AbstractUser, AbstractBaseUser
class Admin(AbstractUser):
class Meta(AbstractUser.Meta):
pass
class HahaUser(AbstractBaseUser):
is_admin = models.BooleanField(default=False, verbose_name='is administrator?')
born = models.PositiveSmallIntegerField(verbose_name='born year')
rating = models.PositiveIntegerField(default=0, verbose_name='user rating')
email = models.EmailField(verbose_name='email')
nickname = models.CharField(max_length=32, verbose_name='useraname')
password = models.CharField(max_length=100, verbose_name='password') # on forms add widget=forms.PasswordInput
language = models.ForeignKey('Language', on_delete=models.PROTECT)
country = models.ForeignKey('Country', on_delete=models.PROTECT)
def __str__(self):
return self.nickname
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
ordering = ['nickname']
class Language(models.Model):
name = models.CharField(max_length=20, verbose_name='language name')
def __str__(self):
return self.name
class Meta:
verbose_name = 'Language'
verbose_name_plural = 'Languages'
class Country(models.Model):
name_ua = models.CharField(max_length=20, verbose_name='country name in Ukranian')
name_en = models.CharField(max_length=20, verbose_name='country name in English')
name_ru = models.CharField(max_length=20, verbose_name='country name in Russian')
def __str__(self):
return self.name_en
class Meta:
verbose_name = 'Country'
verbose_name_plural = 'Countries'
Serializers:
from rest_framework import serializers
from main import models
class RegistrationSerializer(serializers.ModelSerializer):
password2 = serializers.CharField(style={'input_type': 'password'},
write_only=True, required=True)
class Meta:
model = models.HahaUser
fields = ['nickname', 'password', 'password2', 'language', 'country',
'email', 'born']
extra_kwargs = {
'password': {'write_only': True}
}
def save(self):
account = models.HahaUser.objects.create(
email=self.validated_data['email'],
nickname=self.validated_data['nickname'],
language=self.validated_data['language'],
born=self.validated_data['born'],
country=self.validated_data['country']
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match.'})
account.set_password(password)
account.save()
return account
views:
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .serializers import RegistrationSerializer
@api_view(['POST',])
def registration_view(request):
if request.method == 'POST':
serializer = RegistrationSerializer(data=request.data)
data = {}
if serializer.is_valid():
account = serializer.save()
data['response'] = 'Successfully registrated a new user.'
data['email'] = account.email
data['nickname'] = account.nickname
data['language'] = account.language
data['born'] = account.born
data['country'] = account.country
else:
data = serializer.errors
return Response(data)
Full text of error:
Internal Server Error: /api/account/register/
Traceback (most recent call last):
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/django/core/handlers/base.py", line 145, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/django/core/handlers/base.py", line 143, in _get_response
response = response.render()
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/django/template/response.py", line 105, in render
self.content = self.rendered_content
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/rest_framework/response.py", line 70, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/rest_framework/renderers.py", line 103, in render
allow_nan=not self.strict, separators=separators
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/rest_framework/utils/json.py", line 25, in dumps
return json.dumps(*args, **kwargs)
File "/usr/lib/python3.6/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/usr/lib/python3.6/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.6/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/home/dima/Стільниця/hahachat/lib/python3.6/site-packages/rest_framework/utils/encoders.py", line 67, in default
return super().default(obj)
File "/usr/lib/python3.6/json/encoder.py", line 180, in default
o.__class__.__name__)
TypeError: Object of type 'Language' is not JSON serializable
I tried a lot of things: - add json method to language model - post data to field language_id - create LanguageSerializer and work using it but nothing work
Hope to your help))
Upvotes: 0
Views: 1427
Reputation: 3
Thank you for help, but I'd solve it myself.
I just add str() to foreign keys on my view where I generate JSON response.
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .serializers import RegistrationSerializer
@api_view(['POST',])
def registration_view(request):
if request.method == 'POST':
serializer = RegistrationSerializer(data=request.data)
data = {}
if serializer.is_valid():
account = serializer.save()
data['response'] = 'Successfully registrated a new user.'
data['email'] = account.email
data['nickname'] = account.nickname
data['language'] = str(account.language)
data['born'] = account.born
data['country'] = str(account.country)
else:
data = serializer.errors
return Response(data)
Upvotes: 0
Reputation: 85
The result of account.language is an instance. So, in your registration_view
, data['language'] got an instance rather than string or number. That's the reason why data's language is not JSON serializable.
Based on your requirements, you can change it to
data['language'] = account.language.name
Upvotes: 1
Reputation: 4274
As exception says, language
is an object of Language
model and it's not a primitive type. So you should use some attributes of Language model like language_id
or language_name
instead of language object.
from rest_framework import serializers
from main import models
class RegistrationSerializer(serializers.ModelSerializer):
password2 = serializers.CharField(style={'input_type': 'password'},
write_only=True, required=True)
language_name = serializers.CharField(source='language.name')
class Meta:
model = models.HahaUser
fields = ['nickname', 'password', 'password2', 'language_name', 'country',
'email', 'born']
extra_kwargs = {
'password': {'write_only': True}
}
def save(self):
account = models.HahaUser.objects.create(
email=self.validated_data['email'],
nickname=self.validated_data['nickname'],
language=self.validated_data['language_name'],
born=self.validated_data['born'],
country=self.validated_data['country']
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match.'})
account.set_password(password)
account.save()
return account
NOTE: If you fix Language serializable error, You'll get another exception for Country
too.
Upvotes: 1