2012-11-20 14 views
5

moim modelu wygląda następująco:Jak przedłużyć modelu na poziomie serializer z django-Rest-ram

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

Co chciałbym zrobić to narazić listę Components (nie MenuItemComponents) w danym MenuItem że będzie zawierać pole isReplaceable. Do tej pory mam:

#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 

co naraża listę MenuItemComponents i zmusza klientów do dokonywania wielu połączeń w celu pobrania wszystkich składników. Ujawnienie listy komponentów z dodatkowymi danymi z pola isReplaceable rozwiązałoby problem.

EDIT
W końcu chciałbym uzyskać listę z listą elementów składowych ale elementy są exteded z pola isReplaceable z MenuItemComponent modelu

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

Czy możesz podać przykład tego, jak chcesz wyglądać? –

Odpowiedz

8

Najpierw należy utworzyć widok, który będzie powrót instancje MenuItemComponent że jesteś zainteresowany.

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) 

Następnie trzeba stworzyć serializatora dać reprezentację chcesz. Twój przykład jest nieco bardziej interesujący/zaangażowany niż typowym przypadku, tak by to wyglądać mniej więcej tak ...

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

polach „name” i „isReplaceable” może po prostu użyć domyślnego tylko do odczytu Field klasa.

Nie ma pole, które dość spełnia swoją „url” sprawy tutaj, więc będziemy tworzyć niestandardowe pole do tego:

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) 

myślę, że powinny być o prawo.

To jest do serializacji tylko do odczytu - jeśli chcesz mieć zapisywalną serializację, powinieneś przyjrzeć się przesłonięciu metody restore_object w serializatorze i użyciu WritableField lub czegoś podobnego.

+0

Świetnie, to wystarczyło. Dziękuję Ci :). –

+0

Miło to słyszeć. –

Powiązane problemy