【问题标题】:Lack of data with serialization model with ManyToManyField使用 ManyToManyField 的序列化模型缺少数据
【发布时间】:2018-12-21 06:40:47
【问题描述】:

这是我的例子:

models.py:

class Example(models.Model):
    title = models.CharField(...)
    description = models.CharField(...)

class Foo(models.Model):
    example = models.ManyToManyField(Example)

serializers.py:

class FooSerializer(serializers.ModelSerializer):
    class Meta:
        model = Foo
        fields = '__all__'
        depth = 1

views.py:

...
serialized_data = [FooSerializer(foo).data for foo in Foo.objects.all().get]

在输出中,我只收到Example 的 ID,但有什么方法可以让我也获得标题和描述字段(m2mfield 的详细信息)?据我了解,Foo.objects.all().get 根本不包含此数据,但也许我可以以某种方式获取并使用它? 如果需要,我也可以重建模型,但目前我使用 m2mf,因为需要包含与此模型数据相关的多个对象。

更新

models.py

class Event(models.Model):
    ts = models.BigIntegerField(editable=False)

class Foo(Event):
    user = models.ForeignKey(User, ...)
    example = *...(remains to be the same)*
    foos = models.ForeignKey('self', **somemore** null=True)

serializers.py

class EventSerializer(serializers.ModelSerializer):

    class Meta:
        model = Event
        fields = '__all__'

    def to_representation(self, instance):
        result = {'ts': instance.ts}
        if isinstance(instance, Foo):
            result['foo'] = FooSerializer(instance).data
        return result

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username')

class FooSerializer(serializers.ModelSerializer):
   # user = UserSerializer(read_only=True) # with this I have an error: Got AttributeError when attempting to get a value for field 'username' on #serializer 'UserSerializer'

    class Meta:
        model = Foo
        fields = '__all__'
        depth = 1

【问题讨论】:

    标签: python django django-rest-framework manytomanyfield


    【解决方案1】:

    您可以使用depth 属性来实现所需的输出。

    默认的 ModelSerializer 使用主键来表示关系,但是 您还可以使用 depth 轻松生成嵌套表示 option.The depth 选项应该设置为一个整数值 表示之前应该遍历的关系深度 恢复为平面表示

    class FooSerializer(serializers.ModelSerializer):
        class Meta:
            model = Foo
            fields = '__all__'
            depth = 1



    除了答案,我想更改您的 views.py 代码,因为它看起来很糟糕 :(。在 DRF 方式 上做

    serialized_data = FooSerializer(Foo.objects.all(), many=True).data<br>
    

    示例视图

    from rest_framework.viewsets import ModelViewSet
    
    
    class FooViewset(ModelViewSet):
        serializer_class = FooSerializer
        queryset = Foo.objects.all()
    


    UPDATE-1

    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            exclude = ('password',) # add fields that are need to be excluded 
    
    
    class FooSerializer(serializers.ModelSerializer):
        user = UserSerializer()
    
        class Meta:
            model = Foo
            fields = '__all__'
            depth = 1

    depth = 1将序列化model中的all字段,(与在序列化的Meta类中设置fields=='__all__'相同)


    UPDATE-2

    class FooSerializer(serializers.ModelSerializer):
        user = UserSerializer()
    
        class Meta:
            model = Foo
            fields = '__all__'
            depth = 1
    
        def to_representation(self, instance):
            real_data = super().to_representation(instance).copy()
            # DO YOUR EXTRA CHECKS
            child = UserSerializer(instance.child_foo).data
            if child:
                real_data.update({"child_data": child})
            # After your checks, add it to "real_data"
            return real_data

    我假设我有一个Foo 模型

    class Foo(models.Model):
        example = models.ManyToManyField(Example)
        user = models.ForeignKey(User)
        child_foo = models.ForeignKey('self', null=True, blank=True)
    

    【讨论】:

    • 我在 Foo 中有用户的模型 ForeignKey 并通过添加深度它向我显示密码和其他字段。在某些时候我无法序列化用户模型,因为它说AttributeError: Got AttributeError when attempting to get a value for field 'username' on serializer 'UserSerializer' 模型中的许多字段也会发生同样的情况:(
    • 如果你想排除某些字段,你必须定义一个单独的序列化器,即嵌套序列化器
    • 如果您用实际代码相关关系更新您的问题,我可以帮助您更多,即用户模型/抽象用户模型, userserailzer l 等
    • 我不明白你的要求。你把哪个字段设为self-referencing FK,(在哪个模型中)?
    • 你不想覆盖to_representaon() 或任何东西。只需使用depth=2 而不是depth=1 ;)
    【解决方案2】:

    在您的序列化程序中添加深度 = 1。“用户”是相关字段的示例:

    FooSerializer(serializers.ModelSerializer):
        class Meta:
            model = Foo
            fields = ('id', 'account_name', 'users', 'created')
            depth = 1
    

    【讨论】:

      猜你喜欢
      • 2015-12-20
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      相关资源
      最近更新 更多