Проблема
У меня есть модель со следующими стандартными стандартными полями внешнего ключа:
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)