2016-01-07 5 views
6

Ich möchte ein einfaches Modell mit Django REST Framework speichern. Die einzige Anforderung ist, dass UserVote.created_by automatisch innerhalb der perform_create() Methode festgelegt wird. Dies schlägt mit dieser Ausnahme fehl:Django REST Framework: "Dieses Feld ist erforderlich." with required = False und unique_together

{ 
    "created_by": [ 
     "This field is required." 
    ] 
} 

Ich denke, es ist wegen der unique_together index.

models.py:

class UserVote(models.Model): 
    created_by = models.ForeignKey(User, related_name='uservotes') 
    rating = models.ForeignKey(Rating) 

    class Meta: 
     unique_together = ('created_by', 'rating') 

serializers.py

class UserVoteSerializer(serializers.ModelSerializer): 
    id = serializers.IntegerField(read_only=True) 
    created_by = UserSerializer(read_only=True) 

    class Meta: 
     model = UserVote 
     fields = ('id', 'rating', 'created_by') 

views.py

class UserVoteViewSet(viewsets.ModelViewSet): 
    queryset = UserVote.objects.all() 
    serializer_class = UserVoteSerializer 
    permission_classes = (IsCreatedByOrReadOnly,) 

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

Wie kann ich mein Modell in DRF speichern, ohne den Benutzer mit created_by liefern und setzen Sie dieses Feld stattdessen automatisch in Code?

Vielen Dank im Voraus!

Antwort

5

Ich hatte ein ähnliches Problem und ich löste es, indem ich explizit eine neue Instanz an den Serialisierer erstelle und überlasse. Im UserVoteViewSet haben Sie perform_create mit create zu ersetzen:

def create(self, request, *args, **kwargs): 
    uv = UserVote(created_by=self.request.user) 
    serializer = self.serializer_class(uv, data=request.data) 
    if serializer.is_valid(): 
     serializer.save() 
     return Response(serializer.data, status=status.HTTP_201_CREATED) 
    else: 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 
+1

Das ist ordentlich! Klappt wunderbar! Vielen Dank für den Hinweis! –

+0

fehlende Importe. – Nisk

2

Die andere seltsame Art und Weise Sie tun können, verwenden Signale wie diese

@receiver(pre_save, sender=UserVote) 
def intercept_UserVote(sender, instance, *args, **kwargs): 
    import inspect 
    for frame_record in inspect.stack(): 
     if frame_record[3]=='get_response': 
      request = frame_record[0].f_locals['request'] 
      break 
    else: 
     request = None 

    instance.pre_save(request) 

dann im Grunde kann man definieren pre_save in Ihrem Modell

def pre_save(self, request): 
    # do some other stuff 
    # Although it shouldn't happen but handle the case if request is None 
    self.created_by = request.user 
ist

Der Vorteil dieses Systems ist, dass Sie für jedes Modell denselben Code verwenden können. Wenn Sie etwas ändern müssen, ändern Sie einfach in pre_save(). Sie können auch mehr Sachen hinzufügen

Verwandte Themen