Django rest framework serializer.save() return "Invalid data. Expected a dictionary, but got group"

12,862

Based on your LogSerializer, when you pass data attribute to the serializer, it's expecting a dictionary like this:

{
    // note this is a dictionary or a JSON Object.
    // id is omitted because it's auto-inserted natural key
    {
        'name': 'group-name'
    },
    'created': '2017-11-06 20:17:59'
}

but instead, you passed a group instance, where you get from here: group = get_object_or_404(Group, pk=pk) So that raises an Exception when you call .is_valid.

Assuming you are trying to create a Log object with a Group foreign key, for an existing Group, a quick hack would be replacing data = {"group": group } with data = {"group": group.__dict__ }

Share:
12,862
Ng Kei Yin
Author by

Ng Kei Yin

Updated on June 04, 2022

Comments

  • Ng Kei Yin
    Ng Kei Yin almost 2 years

    I am trying to call serlizerer to save object from viewset This is views.py

    class GroupViewSet(viewsets.ViewSet):
            ....
            @detail_route(methods=['post'], url_path='task')
            def get_task(self, request, pk=None):
                group = get_object_or_404(Group, pk=pk)
                data = {"group": group }
                log_serializer = LogSerializer(data=data)
                if log_serializer.is_valid(raise_exception=True):
                    log_serializer.save()
    

    This is serializer.py

    class GroupSerializer(serializers.ModelSerializer):
        class Meta:
            model = Group
            fields = ('id', 'name')
    
    class LogSerializer(serializers.ModelSerializer):
        group = GroupSerializer()
        class Meta:
            model = Log
            fields = ('group', 'created')
    

    This is the model.py:

    class Group:
    ....
    
    class Log(models.Model):
        user = models.ForeignKey(User)
        group = models.ForeignKey(Server) #Not the group of user , it is the group id which user try to query 
        created = models.DateTimeField(auto_now_add=True)
    

    The post responese;

    {
        "group": {
            "non_field_errors": [
                "Invalid data. Expected a dictionary, but got group."
            ]
        }
    }
    
  • Ng Kei Yin
    Ng Kei Yin over 6 years
    Thanks but group.__dict__ will pass the non-readonly field (id would not be passed) into validated_data, so that I can't know which group was passing
  • PatDuJour
    PatDuJour over 6 years
    yes, it would, but the GroupSerializer would only validate the fields you specified. And you are still getting your group from this line: group = get_object_or_404(Group, pk=pk). So if you need to do something about the group object you could too. I guess, let me ask what exactly are you trying to accomplish here because if you are trying to create a nested object, there are better ways to do it.
  • Ng Kei Yin
    Ng Kei Yin over 6 years
    Thanks for the helping, I am not sure is it a nested object. Here is where I want to accomplish , def get_task is the endpoint of getting group task (e.g /group/8/task will get the task of group 8), I want to log down the user who query this and the group she try to query.
  • Ng Kei Yin
    Ng Kei Yin over 6 years
    For now, I am taking the approach provided from stackoverflow.com/questions/29950956/…
  • Ng Kei Yin
    Ng Kei Yin over 6 years
    But it would be great if I can pass the obj directly instead of extract the id then pass
  • PatDuJour
    PatDuJour over 6 years
    I see what you are trying to accomplish now. Yes, that post is actually very helpful, the best approach for nested serializer with foreign key related models is via PrimaryKeyRelatedField. I'm glad you found a solution
  • Ng Kei Yin
    Ng Kei Yin over 6 years
    Thank you for your help!