Django REST框架和通用关系 [英] Django REST Framework and generic relations

查看:191
本文介绍了Django REST框架和通用关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我有一个包含以下标准通用外键字段的模型:

I have a model with the following standard generic foreign key fields:

content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
event_object = generic.GenericForeignKey('content_type', 'object_id')

根据REST框架的文档,我可以执行以下操作来正确序列化:

According to REST framework's docs, I can do the following to serialise this correctly:

class WhateverSerializer(serializers.ModelSerializer):
    event_object = serializers.RelatedField(source='event_object')

这样工作正常,但是在其他两个相关情况下,我无法使工作起作用:

This works fine, however in two other related situations, I can't get things working:


  1. 我想使用 HyperlinkedRelatedField 。此字段需要view_name参数,我不能声明,因为视图名称因相关模型而异。我通过使用 SerializerMethodField 在运行时实例化一个 HyperlinkedIdentityField 来解决这个问题,并返回它的 field_to_native 方法(参见下面的代码段)。

  2. 我想通过说 event_object = SoAndSoSerializer(source ='event_object')
  3. 将相关对象嵌套在序列化中。 code>。我可以看到的唯一的解决方案是走每个 * Serializer 我已经定义并检查哪个具有正确的模型,然后使用它。再次,这并不觉得很优雅。
  1. I would like to use HyperlinkedRelatedField. This field requires the view_name argument, something I can't declare since the view name varies with the related model. I solved this by using SerializerMethodField, instantiating a HyperlinkedIdentityField at runtime and returning its field_to_native method (see snippet below). This does not feel very elegant.
  2. I would like to nest the related object directly in the serialisation by saying event_object = SoAndSoSerializer(source='event_object'). The only solution I can see is to walk every *Serializer I have defined and check which has the correct model, then use that. Again, this does not feel very elegant.

问题

是HyperlinkRelatedField意味着跨通用关系工作?我只是犯了一个错误?有没有一个明显的解决方案来选择我错过的正确的 * Serializer

is HyperlinkRelatedField meant to work across a generic relationship? Am I just making a mistake? Is there an obvious solution to picking the right *Serializer that I'm missing?

代码段

上面第1项提到的不正确的解决方案:

The inelegant solution mentioned in bullet point 1 above:

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)


推荐答案

您的权利,REST框架不支持这些用例,对于我来说,它不是很明显的,如果它是这样的设计。你可能需要一个隐含的model-> view(对于超链接的case)和model-> serializer(对于嵌套的情况)的注册表,我不认为我会很热衷。

Your right, REST framework doesn't support those use cases, and its not obvious to me what the design would look like if it did. You'd probably need an implicit registry of model->view (for the hyperlinked case) and model-> serializer (for the nested case) which I don't think I'd be very keen on.

最简单的方式来做你所需要的可能是子类 ManyRelatedField 并创建自定义字段类型,覆盖 to_native (self,obj)按照所需的方式序列化集合中的每个对象。

The simplest way to do what you need is probably to subclass ManyRelatedField and create a custom field type, overriding to_native(self, obj) to serialize each object in the set exactly the way you want it.

这篇关于Django REST框架和通用关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆