【问题标题】:Django Rest Serializer get data related through Foreign KeysDjango Rest Serializer 通过外键获取相关数据
【发布时间】:2015-10-03 11:53:40
【问题描述】:

我有以下模型骨架:

class A(models.Model):
    post_id = models.ForeignKey('D')
    user_id = models.ForeignKey('B')

class B(AbstractBaseUser):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=20, unique=True)    
    first_name = models.CharField(max_length=40)
    last_name = models.CharField(max_length=40)
    # `resource_id`
    profile_photo = models.ForeignKey('C', null=True)

class C(models.Model):
    user_id = models.ForeignKey('B')
    name = models.CharField(max_length=60)

我想为 A 编写一个序列化程序,它应该从与 B 相关的模型 C 返回 name

这里的关系就像 A->B->C 现在使用 A 的序列化程序,我希望从 C 获取数据

我想通过 A 访问 C,即从 B 获取 profile_photo 并从 C 获取 profile_photo 的名称

我滚动浏览了此处给出的相关字段Django Rest relations,但无法实现我想要的。

他们有什么方法可以实现吗?

除了模型骨架中提到的字段之外,还有很多字段,我不想获取这些字段。

编辑: 我需要的最终结果是来自 A 的特定 post_id 的所有 user_id 以及来自模型 C 的 name

【问题讨论】:

    标签: python django django-views django-rest-framework django-serializer


    【解决方案1】:

    您可以使用ModelSerializer

    注意:我会假设'posts.Post' 是模型C

    class CsSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = C
            fields = ('name')
    
    
    class AsSerializer(serializers.ModelSerializer):
    
        post_id = CsSerializer()
    
        class Meta:
            model = A
            # exclude = ('field_you_dont_want_1', 'field_you_dont_want_2')
            # fields = ('field_you_want_1', 'field_you_want_2')
    

    请注意,在 CsSerializer 中,您可以从模型 C 返回您想要的任何字段,在这种情况下,我只是返回 name

    如果你只需要一个字符串,你可以使用StringRelatedField

    class AsSerializer(serializers.ModelSerializer):
        post_id = serializers.StringRelatedField(many=True)
    
        class Meta:
            model = A
    

    StringRelatedField 将返回 C 模型在 __unicode__ 方法中返回的内容(如果是 python 3.x 则为__str__ 方法)。

    编辑

    现在,根据您的评论,我知道 'posts.Post' 不是 C 模型。所以你可以使用SerializerMethodField:

    class AsSerializer(serializers.ModelSerializer):
        c_name = serializers.SerializerMethodField()
    
        def get_c_name(self, obj):
            return obj.user_id.c_set.values('name')  # this will return a list of dicts with B's related C objects.
    
        class Meta:
            model = A
    

    编辑

    您始终可以在模型中定义类方法:

    class B(AbstractBaseUser):
        email = models.EmailField(unique=True)
        username = models.CharField(max_length=20, unique=True)    
        first_name = models.CharField(max_length=40)
        last_name = models.CharField(max_length=40)
        # `resource_id`
        profile_photo = models.ForeignKey('C', null=True)
    
        def get_profile_photo(self):
            return self.profile_photo.name  # This will return 'C' related object's name
    

    所以当你有一个 A 的对象时:

    a_object.user_id.get_profile_photo()
    

    或者如果你有一个 B 的对象:

    b_object.get_profile_photo()
    

    编辑

    您可以为 C 类定义一个新的序列化器:

    class CsSerializer(serializers.Serializer):
    
        class Meta:
            model = C
    

    然后在你的AsSerializer

    class AsSerializer(serializers.ModelSerializer):
        c_name = serializers.SerializerMethodField()
    
        def get_c_name(self, obj):
            qs = obj.user_id.c_set.all()
            qs_serialized = CsSerializer(qs, many=True)
            return qs_serialized.data
    
        class Meta:
            model = A
    

    【讨论】:

    • 抱歉不清楚,'posts.Post'不是模型C,是其他模型
    • @ofnowhereland 所以你想通过 B 访问 C?
    • 我想通过 A 访问 C,即从 B 获取 profile_photo 并从 C 获取 profile_photo 的名称
    • 搞定了,但我需要对其进行序列化,并且查询集可能包含多个用户,不知道如何实现
    猜你喜欢
    • 2018-10-09
    • 2017-08-19
    • 2015-12-07
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2013-10-20
    • 2016-07-21
    相关资源
    最近更新 更多