【问题标题】:Django Rest Framework Serializer formatDjango Rest Framework 序列化器格式
【发布时间】:2016-01-16 07:25:48
【问题描述】:

我有两个序列化程序:一个用于Restaurant 模型,另一个用于MainMenu 模型:

class RestaurantSerializer(serializers.ModelSerializer):
    class Meta:
        model = Restaurant


class MainMenuSerializer(serializers.ModelSerializer):

    restaurant = RestaurantSerializer()

    main_menu_items = serializers.StringRelatedField(many=True)

    class Meta:
        model = MenuMain
        fields = ('id', 'restaurant', 'main_menu_items')

MainMenuSerializer 的当前输出是

[
    {
        "id": 1,
        "restaurant": {
            "id": 1,
            "name": "Restaurant A",
            "location": "Street B"
        },
        "main_menu_items": [
            "Fried Rice"
        ]
    },
    {
        "id": 2,
        "restaurant": {
            "id": 1,
            "name": "Restaurant A",
            "location": "Street B",
        },
        "main_menu_items": [
            "Noodles"
        ]
    }
]

但我希望 RestaurantSerializer 只输出一次,如下所示:

[
    {
        "restaurant": {
            "id": 1,
            "name": "Restaurant A",
            "location": "Street B"
        }
    },
    [
        {
            "id": 1,
            "main_menu_items": [
                "Fried Rice",
                "Meat Balls"
            ]
        },
        {
            "id": 2,
            "main_menu_items": [
                "Noodles"
            ]
        }
    ]
]

编辑: 使用的模型

class Restaurant(models.Model):
    name = models.CharField(max_length=100, default='')
    location  = models.CharField(max_length=100, default='')

class MenuMain(models.Model):
    price = models.IntegerField()
    restaurant = models.ForeignKey(Restaurant, related_name='main_menus')

class MenuMainItems(models.Model):
    menu_main = models.ForeignKey(MenuMain, related_name='main_menu_items')
    item = models.CharField(max_length=150, default='')

【问题讨论】:

  • 您也可以添加您的模型吗?谢谢。

标签: django serialization django-rest-framework


【解决方案1】:

更多的“Django REST”方式是为每个餐厅设置一个 url 节点,返回餐厅中的所有菜单项。例如,

urls.py

url(r'restaurant-menu/(?P<pk>[0-9]+)$', MenuItemViewset.as_view())

在你的视图类中

class MenuItemViewset(viewsets.ModelViewSet):
    serializer_class = MainMenuSerializer

    def retrieve(self, request, pk=None):
        return Restaurant.objects.get(pk=pk).menumain_set.all()[0].menumainitems_set.all()

这当然假设每家餐厅都有一份菜单。如果有多个菜单并且您想获取所有菜单,最好将其分解为两个调用:一个用于餐厅的菜单,另一个用于获取特定菜单的项目。否则会对数据的组织做出太多假设,这是一种相当脆弱的设计模式。

Link 获取有关获取相关对象的文档

如果您仍然希望获得最初要求的响应,则只需反转序列化程序嵌套,即向 RestaurantSerializer 添加一个菜单字段。

【讨论】:

    【解决方案2】:

    这是我提出的最简单的方法。我知道这可以改进。
    如果您有任何疑问或改进建议,请发表评论。

    class RestaurantSerializer(serializers.ModelSerializer):
    menu = serializers.SerializerMethodField()
    
    
    
    def get_menu(self, obj):
    
        dict_l = {}
        res = MainMenu.objects.all() # filter as per your requirement
        '''
        flds = MainMenu._meta.local_fields
        for ins in res:
            for f in flds:
                print f.name
        '''
        for ins in res:
            dict_l['id'] = ins.id
            dict_l['name'] = ins.name
            dict_l['restaurant'] = ins.restaurant_id
        # return {1: 1, 2: 2}
        return dict_l
    
    class Meta:
        model = Restaurant
        fields = ('id', 'name', 'menu',)
    

    【讨论】:

      猜你喜欢
      • 2015-06-29
      • 2015-10-14
      • 2015-07-01
      • 2016-03-11
      • 2018-10-27
      • 2018-06-23
      • 2016-09-29
      • 2017-07-28
      • 2020-10-30
      相关资源
      最近更新 更多