2013-09-02 9 views
8

Mam książkę model z klucza obcego do użytkownika (właściciela książki):najlepszym sposobem, aby dodać dodatkowe pola do django-rest-ramową ModelViewSet podczas tworzenia

class Book(models.Model): 
    owner = models.ForiegnKey(User) 
    ... 

Utworzyłem ModelViewSet za książkę, która pokazuje książek posiadanych przez zalogowanego użytkownika:

class BookViewSet(viewsets.ModelViewSet): 
    model = Book 
    serializer_class = BookSerializer 
    def get_queryset(self): 
     return Book.objects.filter(owner=self.request.user) 

teraz, aby utworzyć nową książkę, chcę zapisać pole obsługi z request.user, a nie z danych przesyłanych od klienta spoczynku (dla większego bezpieczeństwa). na przykład:

def create(self, request, *args, **kwargs): 
    request.DATA['user'] = request.user 
    ... (some code to create new Book from request.DATA using serialize class) 

ale mam ten błąd: Ta instancja QueryDict jest niezmienna. (oznacza request.DATA jest niezmiennym QueryDict i nie można go zmienić)

Czy znasz lepszy sposób dodawania dodatkowych pól podczas tworzenia obiektu ze strukturą django rest?

Odpowiedz

10

Aktualizacja: Ponieważ v3 trzeba to zrobić:

def perform_create(self, serializer): 
    serializer.save(owner=self.request.user) 

zasada pozostaje taka sama.


Chcesz mieć pole swojej książki serializatora owner tylko do odczytu, a następnie ustawić skojarzenia z użytkownikiem w pre_save().

Coś jak:

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

Zobacz tutorial section on "Associating Snippets with Users".

Mam nadzieję, że to pomaga.

+0

jak ustawić właściciela jako tylko do odczytu w klasie ModelSerializer? – Ali

+0

Po prostu przekazuj read_only = True. Zobacz http://django-rest-framework.org/api-guide/fields.html # core-arguments –

+0

Używam ModelSerializer, a pola są zdefiniowane niejawnie z pól modelu. – Ali

1

Jeśli używasz ModelSerializer jest to tak proste, jak wdrożenie metody restore_object():

class MySerializer(serializers.ModelSerializer): 

    def restore_object(self, attrs, instance=None): 

     create = not instance 
     instance = super(MySerializer, self).restore_object(attrs, instance) 

     if create: 
      instance.user = self.context['request'].user 

     return instance 

    # ... 

restore_object() służy do deserializowania słownika atrybutów do instancji obiektu. ModelSerializerimplements this method i tworzy/aktualizuje instancję dla modelu określonego w klasie Meta. Jeśli podana wartość instance to None, oznacza to, że obiekt musi zostać utworzony. W tym przypadku wystarczy ustawić pole user z żądaną wartością.

Więcej informacji: http://www.django-rest-framework.org/api-guide/serializers#declaring-serializers

6

Na co warto to się zmieniło w Django REST Framework 3. Istnieje teraz perform_create(), który zastępuje starsze podpięcia pre_save() i post_save() zasugerowane w poprzedniej odpowiedzi. Na przykład:

from rest_framework import viewsets 

class MyViewSet(viewsets.ModelViewSet): 
    queryset = MyModel.objects.all() 
    serializer_class = MyModelSerializer 

    def perform_create(self, serializer): 
     serializer.save(owner=self.request.user) 

Mam nadzieję, że to kogoś oszczędza.

+1

Awesome. Po prostu pomniejsza literówka, powinno to być 'def perform_create (self, serializer):' –

Powiązane problemy