Проблема
У меня есть модель со следующими стандартными универсальными полями внешнего ключа:
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
event_object = generic.GenericForeignKey('content_type', 'object_id')
Согласно документам REST framework, я могу сделать следующее, чтобы правильно сериализовать это:
class WhateverSerializer(serializers.ModelSerializer):
event_object = serializers.RelatedField(source='event_object')
Это отлично работает, однако в двух других связанных ситуациях я не могу заставить все работать:
- Я хотел бы использовать
HyperlinkedRelatedField
. Для этого поля требуется аргумент view_name, который я не могу объявить, поскольку имя представления зависит от связанной модели. Я решил эту проблему, используяSerializerMethodField
, создав экземплярHyperlinkedIdentityField
во время выполнения и вернув его методfield_to_native
(см. фрагмент ниже). Это не кажется очень элегантным. - Я хотел бы вложить связанный объект непосредственно в сериализацию, сказав
event_object = SoAndSoSerializer(source='event_object')
. Единственное решение, которое я вижу, — пройтись по каждому*Serializer
, который я определил, и проверить, какая из них имеет правильную модель, а затем использовать ее. Опять же, это не кажется очень элегантным.
Вопросы
предназначено ли HyperlinkRelatedField для работы в общих отношениях? Я просто делаю ошибку? Есть ли очевидное решение, как правильно выбрать *Serializer
, которого мне не хватает?
Фрагмент кода
Неэлегантное решение, упомянутое в пункте 1 выше:
class WhateverSerializer(DefaultSerializer):
event_object_url = serializers.SerializerMethodField('get_related_object_url')
# ...
def get_related_object_url(self, obj):
obj = obj.event_object
default_view_name = '%(model_name)s-detail'
format_kwargs = {
'app_label': obj._meta.app_label,
'model_name': obj._meta.object_name.lower()
}
view_name = default_view_name % format_kwargs
s = serializers.HyperlinkedIdentityField(source=obj, view_name=view_name)
s.initialize(self, None)
return s.field_to_native(obj, None)