2013-12-10 5 views
5

Zacznijmy od modeli używanych w dokumentach django o relacji M2M, która używa argumentu through, aby wskazać model, który będzie działał jako pośrednik.Jak pracować z relacją M2M w django-rest

class Person(models.Model): 
    name = models.CharField(max_length=128) 

    def __unicode__(self): 
     return self.name 

class Group(models.Model): 
    name = models.CharField(max_length=128) 
    members = models.ManyToManyField(Person, 
            through='Membership') 

    def __unicode__(self): 
     return self.name 

class Membership(models.Model): 
    person = models.ForeignKey(Person) 
    group = models.ForeignKey(Group) 
    date_joined = models.DateField() 

    class Meta: 
     ordering = ['date_joined'] 

Załóżmy teraz chcę odpocząć odczytu i zapisu widok na modelu grupy, która zawiera również cały osoba wewnątrz każdej grupy, zamówionego przez date_joined dziedzinie. JSON serializacji chciałbym uzyskać jest następująca (członkowie są opisane tylko z ich ID):

{ 
    "id": 1, 
    "name": "U2", 
    "members": [ 
     20, 
     269, 
     134, 
     12, 
    ] 
} 

Napisałem serializatora:

class GroupSerializer(serializers.ModelSerializer): 
    members = serializers.SlugRelatedField(source='membership_set', 
              many=True, 
              read_only=False, 
              slug_field='person_id', 
              required=True) 

    class Meta: 
     model = Group 
     fields = ('id', 'name', 'members') 

Podczas gdy dla operacji odczytu to działa dobrze, nie służy do pisania. W jaki sposób należy określić serializatora tak, że biorąc pod uwagę powyższe zdefiniowane serializacji, będzie postępować według:

  1. Tworzenie obiektu grupy
  2. dodać każdy członków do grupy (poprzez utworzenie obiektu Membership)

Odpowiedz

2

Od here widać, że to, co próbujesz zrobić, działa tylko w przypadku operacji odczytu. Jest to typowy problem dla DRF, jak stwierdził jego twórca, Tom Christie, w komentarzu this.

Ponadto, dla potrzeb serializacji JSON, zaleca się użycie pola związanego z PK, jak pokazano here, ale to nie pomoże w utworzeniu obiektu grupy i dodaniu członków. Będziesz musiał sam napisać ten kod.

Mam nadzieję, że to pomoże.

Edit

Fragment kodu do dodawania każdą osobę do Grupy poprzez stworzenie Przynależność:

def post_save(self, obj, created=False): 
    # obj represents the Group object 
    if created: 
     # Test to see if the Group was successfully created 
     members = self.request.DATA.get('members', None) 
     if members not None: 
      for id in members: 
       person = Person.objects.get(id=id) 
       membership, m_created = Membership.objects.get_or_create(person=person, group=obj) 
       # Here you can use m_created to see if the membership already existed and to do whatever else you need. 

Implementacja ta zakłada, że ​​zadeklarowali swój date_joined z auto_now. Jeśli nie, powinieneś również przekazać go jako parametr.

+0

Dziękuję za jasną odpowiedź, którą mi dałeś, z linkiem do odpowiedniej części dokumentacji lub odpowiedzi autora na temat. Szkoda, że ​​to, co próbowałem zrobić, nie jest zbytnio wspierane przez ramy. Czy mógłbyś zaproponować mi sposób na wykonanie tego zadania, pisząc kod na własną rękę? Jaka jest właściwa droga? Jeszcze raz dziękuję! – Dragster

+0

Cieszę się, że mogłem pomóc :) Jeśli chodzi o część tworzenia, można to zrobić w dwóch miejscach: w metodzie ** post/create ** lub w metodzie ** post_save **. Sugeruję, aby było to zrobione w ** post_save **, ponieważ oznacza to, że pozwalasz ramowi na tworzenie obiektu Group, a wszystko, co pozostało do zrobienia, to dodawanie członków. Będę edytować moją odpowiedź za pomocą małego fragmentu kodu, aby dowiedzieć się, jak korzystać z tej metody. – AdelaN

+0

Dziękuję bardzo, twoje wsparcie jest bardzo cenne! – Dragster