6

我的模型如下所示:

class MenuItem(models.Model):
    name = models.CharField(max_length=500)
    components = models.ManyToManyField(Component, through=MenuItemComponent)

class Component(models.Model):
    name = models.CharField(max_length=500)

class MenuItemComponent(models.Model):
    menuItem = models.ForeignKey('MenuItem')
    component = models.ForeignKey(Component)
    isReplaceable = models.BooleanField()

我想做的是在给定的 MenuItem 中公开一个包含 isReplaceable 字段的组件列表(不是 MenuItemComponents)。到目前为止,我有:

#views.py

class MenuItemComponentList(generics.ListAPIView):
    """
    Displays components for given MenuItem
    """
    model = MenuItemComponent
    serializer_class = MenuItemComponentSerializer

    def get_queryset(self):
        itemId = self.kwargs['itemId']
        return MenuItemComponent.objects.filter(menuItem__pk=itemId)



#serializers.py

class MenuItemComponentSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MenuItemComponent

它公开了一个 MenuItemComponents 列表并强制客户端进行多次调用以检索所有组件。使用 isReplaceable 字段中的附加数据公开组件列表将解决问题。

编辑
最后,我想获得一个列出 Component 元素的列表,但这些元素是用 MenuItemComponent 模型中的 isReplaceable 字段扩展的:

{
    "count": 2, 
        "next": null, 
        "previous": null, 
        "results": [
        {
            "url": "http://localhost:8000/api/component/1/", 
            "name": "component 1", 
            "isReplaceable": true
        }, 
        {
            "url": "http://localhost:8000/api/component/2/",  
            "name": "component 2",
            "isReplaceable": false
        }
    ]
}
4

1 回答 1

8

首先,创建一个返回您感兴趣的 MenuItemComponent 实例的视图。

class ListComponents(generics.ListAPIView):
    serializer_class = MenuItemComponentSerializer

    def get_queryset(self):
        """
        Override .get_queryset() to filter the items returned by the list.
        """
        menuitem = self.kwargs['menuitem']
        return MenuItemComponent.objects.filter(menuItem=menuitem)

然后你需要创建一个序列化器来给你你想要的表示。你的例子比典型案例更有趣/更复杂,所以它看起来像这样......

class MenuItemComponentSerializer(serializers.Serializer):
    url = ComponentURLField(source='component')
    name = Field(source='component.name')
    isReplaceable = Field()

'name' 和 'isReplaceable' 字段可以简单地使用默认的只读Field类。

这里没有完全符合您的“url”案例的字段,因此我们将为此创建一个自定义字段:

class ComponentURLField(serializers.Field):
    def to_native(self, obj):
        """
        Return a URL, given a component instance, 'obj'.
        """

        # Something like this...
        request = self.context['request']
        return reverse('component-detail', kwargs=kwargs, request=request)

我认为这一切都应该是正确的。

那是针对只读序列化的——如果你想要一个可写的序列化,你需要考虑覆盖restore_object序列化器上的方法,并使用WritableField, 或类似的东西。

于 2012-11-20T12:57:51.017 回答