Django REST Framework: "This field is required." with required = False and unique_together

I want to keep a simple model with the Django REST Framework. The only requirement is that UserVote.created_by set automatically in the perform_create() method. This eliminates this exception:

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

I assume this is due to the unique_interface.

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) 

How can I save my model in DRF without giving the created_by user and instead set this field automatically in the code?

Thanks in advance!

+7
source share
4 answers

I had a similar problem, and I solved it by explicitly creating and passing a new instance to the serializer. In UserVoteViewSet you need to replace perform_create with create :

  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) 
+8
source

Another weird way you can do is use such signals

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

Then basically you can define pre_save in your model

 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 

The advantage of this system is that you can use the same bit of code for each model. If you need to change something, just change it to pre_save() . You can also add more things.

+3
source

I was able to solve this problem with a single line in views.py

 def create(self, request, *args, **kwargs): request.data.update({'created_by': request.user.id}) return super(UserVoteViewSet, self).create(request, *args, **kwargs) 

Since this view expects user authentication, remember to extend permission_classes to rest_framework.permissions.IsAuthenticated

+1
source

Below code works for me.

Even I encountered the same error after many experiments discovered something, so I added all the fields in serializer.py to the meta class, as shown below -

 class Emp_UniSerializer( serializers.ModelSerializer ): class Meta: model = table fields = '__all__' # To fetch For All Fields extra_kwargs = {'std_code': {'required': False},'uni_code': {'required': False},'last_name': {'required': False},'first_name': {'required': False}} 

Here we can update any field that is in "extra_kwargs" , it will not display an error ["This field is required."]

0
source

All Articles