DRF 3 - Creating Many-to-Many update/create serializer with though table

后端 未结 2 455
我寻月下人不归
我寻月下人不归 2021-01-31 18:37

I am trying to create a reference app in DRF 3 to demonstrate a nested serializer that can create/update models. The sample code below bombs with \"*create() argument after **

相关标签:
2条回答
  • 2021-01-31 19:10

    I have no clue if there is an easier way, but the only way I managed to get this to work is to reference the 'through' model "memberships" in the Group serializer and write custom code for .create() and .update(). This seems like a lot of work to just set M2M FK's. If someone knows a better way I'd love to hear it.

    class GroupMembershipSerializer(ModelSerializer):
        class Meta:
            model = Membership
            fields = ('person',)
    
    class GroupCreateSerializer(ModelSerializer):
         memberships = GroupMembershipSerializer(many=True, required=False)
    
        def create(self, validated_data):
            person_data = validated_data.pop('memberships')
            group = Group.objects.create(**validated_data)
            for person in person_data:
                d=dict(person)
                Membership.objects.create(group=group, person=d['person'])
            return group
    
        def update(self, instance, validated_data):
            person_data = validated_data.pop('memberships')
            for item in validated_data:
                if Group._meta.get_field(item):
                    setattr(instance, item, validated_data[item])
            Membership.objects.filter(group=instance).delete()
            for person in person_data:
                d=dict(person)
                Membership.objects.create(group=instance, person=d['person'])
            instance.save()
            return instance
    
        class Meta:
            model = Group
    
    class GroupCreateModelViewSet(ModelViewSet):
        serializer_class = GroupCreateSerializer
        queryset = Group.objects.all()
    

    So you can create a new Group with related Person(s) using:

     { 
         "name" : "Group 1", 
         "memberships" : [ 
             { "person" : 1 },
             { "person" : 2 }
         ]
     }
    
    0 讨论(0)
  • 2021-01-31 19:20

    Use PrimaryKeyRelatedField shown here:

    http://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield

    class GroupSerializer(serializers.ModelSerializer):
        persons = serializers.PrimaryKeyRelatedField(
            many=True, queryset=Person.objects.all())
    
        class Meta:
            model = Group
            fields = ('name', 'persons')
    

    Create each person first, for example. Person with ID 1, Name = "Bob". Person with ID 2, Name = "Tim". Then post them to the REST Endpoint using their primary keys So:

    # Group create() REST endpoint data to POST
    {'name': 'my group', 'persons': [1, 2]}
    

    Now the people that you had created prior, are part of that Group.

    0 讨论(0)
提交回复
热议问题