2016-01-16 4 views
0

J'ai deux serializers: un pour le modèle Restaurant, un autre pour le modèle MainMenu:Django Rest Framework Format sérialiseur

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

La sortie actuelle du MainMenuSerializer est

[ 
    { 
     "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" 
     ] 
    } 
] 

Mais je veux que le RestaurantSerializer pour sortir seulement une fois, quelque chose comme ceci:

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

EDIT: modèles utilisés

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='') 
+0

Pouvez-vous également ajouter vos modèles? Merci. – mariodev

Répondre

0

Plus « Django REST » façon de le faire est de mettre en place un nœud url pour chaque restaurant qui retourne tous les éléments du menu du restaurant. Par exemple,

urls.py

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

Dans votre classe viewset

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

Ceci suppose bien entendu un seul menu par restaurant. S'il y a plusieurs menus et que vous voulez les obtenir tous, il est probablement préférable de le diviser en deux appels: un pour le menu du restaurant, et pour obtenir un menu particulier. Sinon, trop d'hypothèses sont faites sur l'organisation des données, et c'est un modèle de conception plutôt fragile.

Link à docs allant chercher des objets liés

Si vous avez l'intention toujours obtenir une réponse comme vous avez demandé à l'origine pour, il vous suffit d'inverser l'imbrication sérialiseur, à savoir ajouter un champ de menu à RestaurantSerializer.

0

Voici l'approche la plus simple que je suis venu avec. Je sais que cela peut être amélioré.
Veuillez commenter si vous avez des questions ou des suggestions d'amélioration.

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