Подтвердить что ты не робот

Структура Django REST и общие отношения

Проблема

У меня есть модель со следующими стандартными стандартными полями внешнего ключа:

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)
4b9b3361

Ответ 1

Ваше право, REST framework не поддерживает эти прецеденты, и это не очевидно для меня, как будет выглядеть дизайн, если бы это произошло. Вероятно, вам понадобится неявный реестр model- > view (для гиперссылки) и model- > serializer (для вложенного случая), который я не думаю, что буду очень увлекаться.

Самый простой способ сделать то, что вам нужно, - это, вероятно, подкласс ManyRelatedField и создать настраиваемый тип поля, переопределяя to_native(self, obj), чтобы сериализовать каждый объект в наборе точно так, как вам нужно.