【问题标题】:Django Rest Framework: How to add ManyToMany relationships?Django Rest Framework:如何添加多对多关系?
【发布时间】:2019-01-02 08:21:45
【问题描述】:

我想使用 Django Rest Framework 添加多对多关系。实现这一目标的最佳方法是什么?

在 Django shell 级别上,我想做的是说ModelA.model_bs.add(model_b)。如何做到这一点?

我使用generic.CreateAPIView 实现了这一点,并像这样覆盖perform_create() 方法:

def perform_create(self, serializer):
  model_a = self.get_object()
  model_b = ModelB.objects.get(uuid=serializer.validated_data["model_b"]["uuid"])
  model_a.modelbs.add(model_b)

这感觉很奇怪,因为serializer.save() 不再以这种方式被调用。这是一个好方法吗?如果没有,我应该如何实现这一目标?我在文档中找不到任何关于此的内容。

【问题讨论】:

    标签: django django-models django-rest-framework many-to-many


    【解决方案1】:

    不确定是否有更复杂的事情发生,因为您没有展示您的模型,但对于简单的ManyToMany 关系,最简单的解决方案就是使用PrimaryKeyRelatedField。比如:

    class ModelASerializer(serializers.ModelSerializer):
        model_b = serializers.PrimaryKeyRelatedField(many=True, read_only=False)
    

    然后您将通过 API 通过更新将对象添加到此字段。

    更新

    如果使用uuid 字段而不是在API 上公开主键很重要,我建议使用SlugRelatedField,它旨在“使用目标上的字段表示关系的目标”:

    class ModelASerializer(serializers.ModelSerializer):
        model_b = serializers.SlugRelatedField(
            many=True, 
            slug_field='uuid',
            queryset=ModelB.objects.all()
        )
    

    注意:对于SlugRelatedFieldread_only 默认为 False,但您确实需要指定查询集。

    【讨论】:

    • 我的模型没什么复杂的。非常感谢您使用更新路线的提示!不幸的是,我不能使用 PrimaryKeyRelatedField,因为我们公司有严格的政策来发布 pk。所以外面的世界一定不能没有钥匙。
    • 我已经更新添加了一个考虑到您的限制的版本。
    【解决方案2】:

    您可以通过以下方式实现:

    型号

    from django.db.models import Model, ManyToManyField
    
    
    class Employee(Model):
        company = ManyToManyField(Company)
    

    序列化器

    from rest_framework.serializers import ModelSerializer, IntegerField, RelatedField
    
    
    class CompanyRelatedField(RelatedField):
        def to_representation(self, obj):
            data = {
                'id': obj.id,
                'title': obj.title
            }
            return data
    
        def to_internal_value(self, id):
            return Company.objects.get(id=id)
    
    
    class EmployeeSerializer(ModelSerializer):
        id = IntegerField(read_only=True)
        company = CompanyRelatedField(
            queryset=Company.objects.all(), many=True, required=True
        )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-12
      • 2023-03-08
      • 1970-01-01
      • 2019-02-26
      相关资源
      最近更新 更多