【问题标题】:Link ManyToManyFiled with the corresponding Model API将 ManyToManyFiled 与相应的模型 API 链接
【发布时间】:2019-07-17 08:32:53
【问题描述】:

我有两个模型“书”和“作者”。我在“作者”模型中有作者详细信息。我正在使用 API 创建“书籍”。我想使用“Author_id”将“Author”与“Book”链接起来。

我试过下面的代码。

models.py:

class Author(models.Model):
   name = models.CharField(max_length=64)

class Book(models.Model):
   name = models.CharField(max_length=64)
   author = models.ManyToManyField(Author,related_name='author')

views.py

 class BookListView(APIView):

    def post(self, request, format=None):
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():
           serializer.save()
           return Response(serializer.data, 
        status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializer.py:

  class AuthorSerializer(serializers.ModelSerializer):
       class Meta:
           model = Author
           fields = ('name', )

  class BookSerializer(serializers.ModelSerializer):
      assessments = AuthorSerializer(many=True, required=False)

      class Meta:
         model = Book
         fields = ('name', 'authors')


       def create(self, validated_data):
          print(validated_data)
          authors = validated_data.pop('authors')
          book = Book(**validated_data)
          book.save()
          return book

我在“作者”表中有以下作者。

  id        name
  1         Alex
  2         John
  3         Bob

用于创建图书的示例 JSON 文件:

   {
     "name":"Product 002",
     "authors":
        [
          {
            "author_id":2
          },
          {
            "author_id":1
          }
        ]
    }

保存图书时会出现以下错误。

    {
      "authors": [
         {
            "name": [
               "This field is required."
           ]
         },
         {
            "name": [
               "This field is required."
             ]
          }
       ]
   }

Json 文件 2:

  {
     "name":"Product 002",
     "authors":
        [
          {
            "name": Alex,
            "author_id":1
          },
          {
            "name": "John"
            "author_id":1
          }
        ]
    }

保存图书时会出现以下错误。

    {
      "authors": [
          {
            "name": [
                  "author with this name already exists."
             ]
          },
          {
              "name": [
                  "author with this name already exists."
              ]
          }
      ]
   }

请帮我解决问题。提前致谢

【问题讨论】:

    标签: django python-3.x django-rest-framework


    【解决方案1】:

    您需要在创建图书时为作者提供name,因为图书序列化器需要一个 AuthorSerializer,它需要 name 字段 (fields = ('name', ))。

    你可以做以下3个解决方案:

    1. 给出您的序列化程序期望的内容,像这样更改您的请求正文:
    {
         "name":"Product 002",
         "authors":
            [
              {
                "author_id":2,
                "name":"John"
              },
              {
                "author_id":1,
                "name":"Alex"
              }
            ]
    }
    
    1. 编辑AuthorSerializer,使其不期望name,而只期望id
    class AuthorSerializer(serializers.ModelSerializer):
           class Meta:
               model = Author
               fields = ('id', )
    
    1. 更改 BookSerializer 使其仅按 id 对作者进行序列化:
    class BookSerializer(serializers.ModelSerializer):
        authors = serializers.PrimaryKeyRelatedField(
            many=True,
            queryset=Authors.objects.all()
        )
    
        class Meta:
            model = Book
            fields = ('name', 'authors')
    

    您的请求正文将是:

    {
         "name":"Product 002",
         "authors": [1, 2]
    }
    
    

    【讨论】:

    • 我也尝试过以下 JSON 文件。 { "name":"Product 002", "authors": [ { "name":"Alex", "author_id":1 }, { "name":"John", "author_id":2 } ] } 它抛出以下错误。 { "authors": [ { "name": [ "使用此代码的作者已经存在。" ] }, { "name": [ "使用此代码的作者已经存在。" ] } ] }
    • 你这是什么意思?我为您展示了 3 种不同的解决方案。
    • 实际上它并没有将作者与书籍联系起来。我将在请求正文中提供作者姓名的同时创建新作者。请帮助我避免新创建作者
    • 如果要在正文中创建新作者,需要先从数据库中删除现有作者,或者在正文中添加新作者。据我所知,您提供的作者 ID 已经存在于您的数据库中。
    • 不,我不想创建新作者。我想通过在请求正文中提供作者姓名来将作者模型与 Book 链接。作者姓名已使用单独的 API 创建。在我的 API 中,我想将现有作者与 Book 链接
    【解决方案2】:

    我有一个解决方案。 你将不得不改变你的 serializers.py

    class AuthorSerializer(serializers.ModelSerializer):
        class Meta:
            model = Author
            fields = ('id', 'name', )
    
    class BookSerializer(serializers.ModelSerializer):
        authors= serializers.SerializerMethodField(required=False)
    
        class Meta:
            model = Book
            fields = ('name', 'authors')
    
        def create(self, validated_data):
            print(validated_data)
            book = Book(**validated_data)
            book.save()
            return book
    
        @staticmethod
        def get_authors(obj):
            return AuthorSerializer(obj.author.all(), many=True).data
    

    通过声明

    authors= serializers.SerializerMethodField(required=False)
    

    您可以在列表中传递作者的主键(在ManyToManyField中,它的类型设置为不是List,但可以发送列表来存储作者),同时返回带有作者ID和姓名列表的json序列化数据。

    您的 json 请求正文将是:

    {
         "name":"Product 002",
         "authors": [1, 2]
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-27
      • 2016-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多