Django Rest Framework Serializer格式

时间:2016-01-16 07:25:48

标签: django serialization django-rest-framework

我有两个序列化程序:一个用于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='')

2 个答案:

答案 0 :(得分:0)

更多" Django REST"这样做的方法是为每个餐厅设置一个url节点,返回餐厅中的所有菜单项。例如,

<强> urls.py

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        LinearLayout actionItemLayout = (LinearLayout) menu.findItem(R.id.item_save).getActionView();
        ImageView iv = (ImageView)actionItemLayout.findViewById(R.id.actionItemImage);
        iv.setBackgroundDrawable(getResources().getDrawable(R.drawable.icon_save));
}

在您的视图集类中

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

这当然假设每个餐厅有一个菜单。如果有多个菜单并且您希望获得所有这些菜单,那么最好将其分成两个电话:一个用于餐厅的菜单,并获得特定的菜单。项目。否则,对数据的组织做出了太多的假设,而这是一个相当脆弱的设计模式。

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

如果您仍然想要获得最初要求的响应,则只需要反转序列化器嵌套,即将菜单字段添加到RestaurantSerializer。

答案 1 :(得分:0)

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

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',)