Если у меня есть GFK, такие как модели наследования Assets (Asset.model, имеющий asset_id, asset_name и Account, OneType.model, SecondType.model, все наследуются от модели Asset и т.д. на основе это), и я хочу предоставить Конечная точка API для всех активов в моем Account, я мог бы иметь (не уверен, что это соглашение) свойство модели Account, которое представляет собой список, расширяющий различные типы активов:
#Account model
@property
def assets(self):
assets = []
assets.extend(self.onetype_set.all())
assets.extend(self.secondtype_set.all())
…
return assets
Мне понадобится сериализатор для учетной записи
class AccountSerializer(serializers.ModelSerializer):
# filter to assets for the user
def get_queryset(self):
return Account.objects.filter(organization=self.request.user)
class Meta:
model = Account
fields = ('assets', )
и я предполагаю, что для каждого типа активов
class OneTypeSerializer(serializers.ModelSerializer):
class Meta:
model = OneType
fields = ('asset_id', 'asset_name',)
class SecondTypeSerializer(serializers.ModelSerializer):
…
…
но я продолжаю получать сообщение об ошибке: Object of type 'OneType' is not JSON serializable (я понимаю, что ошибка означает, что мне нужно, чтобы модель была сериализована в JSON, но я думал, что модель вызовет сериализатор модели ...)
Трассировка стека кажется бесполезной из-за внутренней работы наборов представлений DRF, но вот она:
/usr/local/Cellar/python/3.6.5_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py in default
else:
return list(iterable)
# Let the base class default method raise the TypeError
return JSONEncoder.default(self, o)
"""
raise TypeError("Object of type '%s' is not JSON serializable" %
o.__class__.__name__) ...
def encode(self, o):
"""Return a JSON string representation of a Python data structure.
>>> from json.encoder import JSONEncoder
>>> JSONEncoder().encode({"foo": ["bar", "baz"]})
▼ Local vars
Variable Value
o <OneType: AssetName - Type 1 : Account 2>
self <rest_framework.utils.encoders.JSONEncoder object at 0x11dce1668>
Viewsets.py:
class AssetViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`, `update` and `destroy` actions.
"""
serializer_class = AssetSerializer
permission_classes = (permissions.IsAuthenticated, IsOrganizationMember,)
def get_queryset(self):
slug = self.kwargs['slug']
return Account.objects.filter(slug=slug)
Кроме того, это скорее проблема DRF (я не использую правильный набор запросов) или проблема с питоном (я не предоставляю сериализуемый метод / класс для объекта / класса)?
Обратите внимание, что объявление OneTypeSerializer с model = OneType в его мета-мете не включает автоматическую сериализацию OneType с этим сериализатором во всех местах.
Также обратите внимание на Документы DRF о вложенных отношениях. Как вы можете видеть в примере, сериализатор для дочернего поля должен быть явно объявлен для родительского поля.
@chris Frisina похоже, что вы пытаетесь вернуть экземпляр OneType из класса / функции просмотра. Итак, проверьте представление или добавьте соответствующее представление
Вам нужно будет предоставить свой код представления, чтобы получать более полезные ответы.
@JPG, Все они основаны на базовых классах.
Приведенные здесь фрагменты кода не показывают, как предполагается сериализовать ресурсы. Мы мало чем можем здесь помочь.
@Linovia, на самом деле я заставил его работать, выполнив следующие действия в сериализаторе учетных записей assets = serializers.StringRelatedField (many = True), на который намекал из заметок Михаила, но я думаю, что могут быть другие способы, возможно, с разными архитектурами, учитывая разные подходы к ГФК вроде проблем. Оставайся позитивным!






Это явно проблема DRF, хотя в то время я не помню, какой для этого был бы правильный код. Я предполагаю, что вам нужно назначить
assets = ...в вашем классе AccountSerializer, но вместо..., вероятно, должен быть какой-то волшебный полиморфный сериализатор, который применял бы правильный сериализатор для каждого элемента списка.