【问题标题】:Django REST: TypeError: Object of type 'Language' is not JSON serializableDjango REST:TypeError:“语言”类型的对象不是 JSON 可序列化的
【发布时间】:2020-06-20 00:54:22
【问题描述】:

当我尝试添加语言 python3 的值时返回此对象不是 JSON 可序列化的错误。

型号:

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'

序列化器:

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

观看次数:

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)

错误全文:

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

我尝试了很多东西: - 在语言模型中添加 json 方法 - 将数据发布到字段 language_id - 创建 LanguageSerializer 并使用它 但没有任何效果

希望对您有所帮助))

【问题讨论】:

    标签: python json django python-3.x django-rest-framework


    【解决方案1】:

    account.language 的结果是一个实例。因此,在您的registration_view 中,data['language'] 得到了一个实例,而不是字符串或数字。这就是为什么数据的语言不是 JSON 可序列化的原因。

    根据您的要求,您可以将其更改为

    data['language'] = account.language.name

    【讨论】:

      【解决方案2】:

      正如例外所说,languageLanguage 模型的对象,它不是原始类型。所以你应该使用语言模型的一些属性,比如language_idlanguage_name,而不是语言对象。

      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
      

      注意:如果您修复 Language serializable 错误,您也会得到 Country 的另一个异常。

      【讨论】:

        【解决方案3】:

        谢谢你的帮助,但我会自己解决。

        我只是将 str() 添加到生成 JSON 响应的视图上的外键。

            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)
        

        【讨论】:

          猜你喜欢
          • 2020-03-04
          • 2020-12-13
          • 2019-09-22
          • 2021-08-29
          • 2022-07-01
          • 2023-01-10
          • 2019-04-29
          • 2019-06-25
          • 2020-12-02
          相关资源
          最近更新 更多