2

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
  • 31
  • 1
  • 1
  • 4

1 Answers1

2

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__ }

PatDuJour
  • 893
  • 1
  • 10
  • 25
  • 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 – Ng Kei Yin Nov 08 '17 at 02:55
  • 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. – PatDuJour Nov 08 '17 at 04:49
  • 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 Nov 08 '17 at 06:53
  • For now, I am taking the approach provided from https://stackoverflow.com/questions/29950956/drf-simple-foreign-key-assignment-with-nested-serializers – Ng Kei Yin Nov 08 '17 at 07:00
  • But it would be great if I can pass the obj directly instead of extract the id then pass – Ng Kei Yin Nov 08 '17 at 07:02
  • 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 – PatDuJour Nov 08 '17 at 07:21
  • Thank you for your help! – Ng Kei Yin Nov 08 '17 at 07:47