使用Django Rest作為后端在做的項(xiàng)目中,Model是這樣的:
class Sample(models.Model):
...
creater = models.ForeignKey(User, on_delete=models.CASCADE)
...
Serializers是這樣:
class SampleSerializer(serializers.ModelSerializer):
class Meta:
model = Sample
fields = (...,'creater')
Views是這樣:
class SampleList(generics.ListCreateAPIView):
queryset = Sample.objects.all()
serializer_class = SampleSerializer
permission_classes = (IsOwnerOrReadOnly,)
def perform_create(self, serializer):
...
serializer.save(creater=self.request.user,...)
問題是,我在執(zhí)行插入的時(shí)候,總是提示:
{"creater": ["This field is required."]}
百思不得其解,因?yàn)槊髅魍ㄟ^creater=self.request.user賦值了啊。
后來在Model中,將creater字段修改為
creater = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
問題解決。
但這是為什么呢?谷歌后發(fā)現(xiàn):
The perform_create method is called by your View's create method after serializer validation. At this stage, DRF will have found and flagged the missing user field.
原來視圖中的perform_create操作晚于serializer的校驗(yàn)。上面的代碼中,perform_create前DRF已經(jīng)發(fā)現(xiàn)creater字段的缺失。
來看看rest_framework的源碼:
class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
解決這個(gè)問題的方法有多種,除了上面的null=True, blank=True之外,還可以:
- 在
serializer中設(shè)置這個(gè)字段readonly=True,或 - 在
serializer中重載validate_user,或 - 使用DFR的
currentuserdefault校驗(yàn)器。
參考地址。