Почему django не использует мой класс кодировщика? - PullRequest
0 голосов
/ 06 ноября 2018
  1. У меня есть два класса: Website и WordpressWebsite.
  2. WordpressWebsite подклассы Website.

Когда экземпляр WordpressWebsite кодируется в JSON, присутствуют только атрибуты WordpressWebsite (и ни один из атрибутов Website).

Моя цель - написать собственный кодер, который вместо этого будет кодировать WordpressWebsite как веб-сайт.

Это то, что я имею до сих пор:

from django.core.serializers.json import DjangoJSONEncoder
from websites.models import Website

class WebsiteEncoder(DjangoJSONEncoder):

    def default(self, obj):
        raise Exception()  # TEST
        if isinstance(obj, Website) and hasattr(obj, 'website_ptr'):
            return super().default(obj.website_ptr)
        return super().default(obj)

У меня есть следующий контрольный пример:

from django.core import serializers
from django.test import TestCase
from websites.models.wordpress import WordpressWebsite
from websites.serialize import WebsiteEncoder


class SerializationTest(TestCase):

    def setUp(self):
        self.wordpress = WordpressWebsite.objects.create(
            domain='test.com'
        )

    def test_foo(self):
        JSONSerializer = serializers.get_serializer("json")
        json_serializer = JSONSerializer()
        json_serializer.serialize(
            WordpressWebsite.objects.all(),
            cls=WebsiteEncoder
        )
        data = json_serializer.getvalue()
        print(data)

Этот тестовый пример работает нормально. Это не вызывает исключения.

Кто-нибудь знает, почему WebsiteEncoder.default не вызывается?

1 Ответ

0 голосов
/ 07 ноября 2018

Модели Django изначально кодируются своими сериализаторами. Собственный Django DjangoJSONEncoder предоставляет полный сериализатор для всех возможных моделей с любым типом данных Django по умолчанию. Если вы посмотрите документацию JSONEncoder.default() , вы заметите, что поставляете кодировщики только для типов данных, которые еще не известны кодировщику.

Только если вы использовали тип поля, который Django изначально не поддерживает, вы можете предоставить кодировщик для него - и только этот тип поля - через .default(). Поэтому DjangoJSONEncoder не то, что вы ищете.

Пытаясь заставить ваш пример работать, я обнаружил, что вы можете на самом деле настроить процесс, создав подкласс django.core.serializers.json.Serializer:

from django.core.serializers.json import Serializer

class WebsiteSerializer(Serializer):
    def get_dump_object(self, obj):
        return {
            "pk": obj.pk,
            **self._current,
        }

После этого вы можете заставить ваш сериализатор работать в тестовом примере следующим образом:

def test_foo(self):
    serializer = WebsiteSerializer()
    data = serializer.serialize(WordpressWebsite.objects.all())
    print(data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...