2016-01-07 17 views
6

Django REST Frameworkを使用して単純なモデルを保存します。唯一の要件はperform_create()メソッド内でUserVote.created_byが自動的に設定されることです。これは、この例外で失敗します:Django RESTフレームワーク: "このフィールドは必須です。" with必須= Falseおよびunique_together

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

私はそれがunique_togetherインデックスのためだと思います。

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) 

どのように私はcreated_byを供給するために、ユーザーがなくても、DRFの私のモデルを保存することができます代わりにこのフィールドをコードで自動的に設定しますか?

ありがとうございます!

答えて

5

私は同様の問題があり、シリアライザに新しいインスタンスを明示的に作成して渡すことで解決しました。

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

これはすてきです!魅力的な作品!ヒントのためにありがとう! –

+0

が不足しています。 – Nisk

2

あなたが行うことができ、他の奇妙な方法は、この

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

のような使用信号はその後、基本的に、あなたのモデルに

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 
をpre_saveを定義することができます: UserVoteViewSetあなたが createperform_createを代用する必要がで

このシステムの利点は、すべてのモデルで同じコードのビットを使用できることです。何かを変更する必要がある場合は、pre_save()に変更してください。あなたも同様に多くのものを追加することができます