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()

私がやりたいのは、isReplaceableフィールドを含む特定のMenuItem内のコンポーネント(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フィールドからの追加データでコンポーネントリストを公開すると、問題が解決します。

編集
最後に、コンポーネント要素をリストするリストを取得したいのですが、要素は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 に答える