2013-04-08 3 views
8

Używam Django REST Framework do tworzenia interfejsu API dla mojej aplikacji internetowej. Mam klasy "Komentarz", który ma depth=2 ustawiony w klasie Meta. Działa to świetnie, gdy GET ing Comments. Kiedy próbuję wysłać żądanie POST lub PUT (tj. Utworzyć nową Comment), powiedziano mi, że muszę dołączyć obiekty zamiast identyfikatorów kluczy obcych.Django REST Struktura inna głębokość dla POST/PUT?

Oto moja klasa serializer:

class CommentSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Comment 
     depth = 2 

Model:

class Comment(models.Model): 
    user = models.ForeignKey(User, null=True, blank=True, 
     related_name='comments') 
    budget = models.ForeignKey(Budget, related_name='comments') 
    published = models.BooleanField(default=False) 
    body = models.TextField() 
    created = models.DateTimeField(auto_now_add=True) 

Kod widok:

class Comments(generics.ListCreateAPIView): 

    model = Comment 
    serializer_class = CommentSerializer 

    def pre_save(self, obj): 
     obj.user = self.request.user 

i błąd, który jest wyświetlany na wyjściu (JSON) jest :

{"user": ["This field is required."], "budget": [{"non_field_errors": ["Invalid data"]}]} 

Kiedy to surowe dane są wysyłane:

{"budget": 2, "published": true, "body": "Another comment"} 
+0

Losowe pytanie, co się stanie, jeśli wyślesz '{" budget_id ": 2}' lub '{" budget ": {" id ": 2}}'? –

+0

RE @Nathan Villaescusa. następnie oczekuje, że w innych polach budżetu będą one wyświetlane zgodnie z wymaganiami. – panchicore

Odpowiedz

6

wierzę właściwy sposób zdefiniować pole serializer który odnosi się do relacji klucza obcego jest przez coś podobnego serializers.PrimaryKeyRelatedField. Nie wierzę, że serializatory modeli automatycznie używają tej klasy pól bez jej wyraźnego zdefiniowania w klasie serializera.

http://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield

Mogę sobie wyobrazić, że PrimaryKeyRelatedField serializer by prawidłowo obsługiwać zgłoszenia danych JSON, jak ten, który wykorzystano w przykładzie.

+6

Dla tych, którzy przybyli tutaj z Google, Tom Christie (twórca DRF) napisał więcej na ten temat tutaj: https://groups.google.com/d/msg/django-rest-framework/vCl2I_EzJnE/qwRdIdxiUe4J –

6

Wiem, że to trochę późno, ale skończyło się za pomocą 2 serializers tak:

class CommentReadSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Comment 
     depth = 2 

class CommentWriteSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Comment 

następnie wykorzystywane tak:

class Comments(generics.ListCreateAPIView): 

    model = Comment 
    serializer_class = CommentReadSerializer 

    def create(self, request, *args, **kwargs): 
     serializer = CommentWriteSerializer(data=request.DATA, files=request.FILES) 
     if serializer.is_valid(): 
      self.pre_save(serializer.object) 
      self.object = serializer.save(force_insert=True) 
      self.post_save(self.object, created=True) 
      headers = self.get_success_headers(serializer.data) 
      serializer = CommentReadSerializer(serializer.object) 
      return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) 

     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 
1

Można ustawić różne serializers poprzez nadpisanie get_serializer_class() funkcja, tak:

def get_serializer_class(self): method = self.request.method if method == 'PUT' or method == 'POST': return YourWriteSerializer else: return YourReadSerializer

Zastanowiłem się nad dodaniem tego, ponieważ po pewnym czasie przyjechałem tu z Googling.