Django Generic Relations - ** 类型的对象不是 JSON 可序列化的

Posted

技术标签:

【中文标题】Django Generic Relations - ** 类型的对象不是 JSON 可序列化的【英文标题】:Django Generic Relations - Object of Type ** is Not JSON Serializable 【发布时间】:2019-09-22 20:59:25 【问题描述】:

对 Django 还是新手,所以请耐心等待。

我正在尝试遵循 Django 示例https://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/。

我正在尝试使用 tests.py 为学生 1 创建笔记。

这里是tests.py:

from django.test import TestCase
from gsndb.models import *
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User

# Create your tests here.

student = Student.objects.get(id=4)
text = "The student is content"
user = User.objects.get(id=2)

new_note = Note(text=text, content_object = student, user = user)

new_note.save()

我希望它为学生 1 创建一个注释。但是当我运行测试时,我收到此错误:

Object of type 'Student' is not JSON serializable

这是回溯:

Environment:


Request Method: GET
Request URL: http://localhost/gsndb/note/

Django Version: 2.1.7
Python Version: 3.6.8
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'corsheaders',
 'rest_framework',
 'user_app.apps.UserAppConfig',
 'gsndb.apps.GsndbConfig']
Installed Middleware:
['corsheaders.middleware.CorsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/usr/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  156.                 response = self.process_exception_by_middleware(e, request)

File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  154.                 response = response.render()

File "/usr/lib/python3.6/site-packages/django/template/response.py" in render
  106.             self.content = self.rendered_content

File "/usr/lib/python3.6/site-packages/rest_framework/response.py" in rendered_content
  72.         ret = renderer.render(self.data, accepted_media_type, context)

File "/usr/lib/python3.6/site-packages/djangorestframework_camel_case2/render.py" in render
  9.                                                          **kwargs)

File "/usr/lib/python3.6/site-packages/rest_framework/renderers.py" in render
  107.             allow_nan=not self.strict, separators=separators

File "/usr/lib/python3.6/site-packages/rest_framework/utils/json.py" in dumps
  28.     return json.dumps(*args, **kwargs)

File "/usr/lib/python3.6/json/__init__.py" in dumps
  238.         **kw).encode(obj)

File "/usr/lib/python3.6/json/encoder.py" in encode
  199.         chunks = self.iterencode(o, _one_shot=True)

File "/usr/lib/python3.6/json/encoder.py" in iterencode
  257.         return _iterencode(o, 0)

File "/usr/lib/python3.6/site-packages/rest_framework/utils/encoders.py" in default
  68.         return super(JSONEncoder, self).default(obj)

File "/usr/lib/python3.6/json/encoder.py" in default
  180.                         o.__class__.__name__)

Exception Type: TypeError at /gsndb/note/
Exception Value: Object of type 'Student' is not JSON serializable

这里是models.py

class Note(models.Model):
    user = models.ForeignKey(
        get_user_model(),
        on_delete = models.PROTECT,
    )
    created = models.DateTimeField(default = timezone.now)
    text = models.TextField()

    # Below the mandatory fields for generic relation
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type','object_id')

class Student(models.Model):
    current_school = models.ForeignKey(
        "School",
        null = True,
        on_delete = models.PROTECT,
    )
    current_program = models.ForeignKey(
        "Program",
        null = True,
        on_delete = models.PROTECT,
    )
    first_name = models.CharField(max_length = 35, blank=True)
    last_name = models.CharField(max_length = 35, blank=True)
    middle_name = models.CharField(max_length = 35, blank=True)
    """Establish choices for Gender"""
    GENDER_CHOICES = (
        ("M", 'Male'),
        ("F", 'Female'),
        ("NB", 'NonBinary'),
    )
    gender = models.CharField(
            max_length = 2,
            blank = True,
            choices = GENDER_CHOICES,
    )
    birth_date = models.DateField(null = True)
    state_id = models.BigIntegerField(null = True)
    """Establish choices for Grade Year"""
    GRADE_YEAR_CHOICES = (
        (0, 'Kindergarten'),
        (1, 'First Grade'),
        (2, 'Second Grade'),
        (3, 'Third Grade'),
        (4, 'Fourth Grade'),
        (5, 'Fifth Grade'),
        (6, 'Sixth Grade'),
        (7, 'Seventh Grade'),
        (8, 'Eighth Grade'),
        (9, 'Ninth Grade'),
        (10, 'Tenth Grade'),
        (11, 'Eleventh Grade'),
        (12, 'Twelfth Grade'),
    )
    grade_year = models.SmallIntegerField(
        choices = GRADE_YEAR_CHOICES,
        null = True,
    )
    reason_in_program = models.TextField(blank=True)
    notes = GenericRelation(Note)

这里是serializers.py:

class NoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = ("user",
            "created",
            "text",
            "content_type",
            "object_id",
            "content_object")

class StudentSerializer(serializers.BaseSerializer):

        def to_representation(self, student_obj):
            notes = NoteSerializer(many = True)
            notes_json = notes.data

            return 
                "current_school": student_obj.current_school.id,
                "current_program": student_obj.current_program.id,
                "first_name": student_obj.first_name,
                "last_name": student_obj.last_name,
                "middle_name": student_obj.middle_name,
                "gender": student_obj.gender,
                "birth_date": student_obj.birth_date,
                "state_id": student_obj.state_id,
                "grade_year": student_obj.grade_year,
                "reason_in_program": student_obj.reason_in_program,
                "notes": notes_json,
            

这是我的views.py:

class NoteList(generics.ListCreateAPIView):
    queryset = Note.objects.all()
    serializer_class = NoteSerializer

感谢您的宝贵时间!

【问题讨论】:

在这一行 'new_note = Note(text=text, content_object = student, user = user)' 如果您的意思是创建新对象,然后像这样创建: new_note = Note.objects.create(text=text, content_object = student, user = user) @chiragsoni 谢谢!能问下有什么区别吗?此外,它仍然导致相同的错误,即 student 不是 json 可序列化的。有什么想法吗? 阅读:***.com/questions/26672077/… 谢谢!知道为什么它仍然说学生不是 json 可序列化的 【参考方案1】:

找出我的问题。在我看来。

我的看法是

class NoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = ("user",
            "created",
            "text",
            "content_type",
            "object_id",
            "content_object")

我需要删除“content_object”,因为它不是 JSON 可序列化的。它需要看起来像这样:

class NoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = ("user",
            "created",
            "text",
            "content_type",
            "object_id")

感谢大家的帮助!

【讨论】:

以上是关于Django Generic Relations - ** 类型的对象不是 JSON 可序列化的的主要内容,如果未能解决你的问题,请参考以下文章

django 1.9 中的 from django.views.generic.simple import direct_to_template 相当于啥

Django-简述generic views

python - Django4 - 表格&generic view

Django ORM框架

python 没有PK或Slug的Django Generic DetailView

Django Generic Views:教程中,DetailView如何自动提供变量?