DRF 测试 - 创建具有多对多关系的对象

DRF testing - create object with a many-to-many relation

我有以下模型项目:

class Project(models.Model):
    name = models.CharField(max_length=128)
    slug = models.SlugField(blank=True)
    assigned_to = models.ManyToManyField(
        User, blank=True, related_name="assignees")
    created_date = models.DateField(auto_now_add=True)
    updated_date = models.DateField(auto_now_add=False, auto_now=True)

如果我需要创建一个新项目,我需要做的就是单独提供 name。这适用于管理仪表板和 DRF APIVIEW。但是,当我尝试通过 API 调用使用 DRF 测试功能时,出现错误:[b'{"assigned_to":["This field is required."]}'] 虽然该字段不是必需的。

下面是我的测试代码

import datetime
from marshmallow import pprint

from rest_framework.test import APITestCase, APIClient
from freezegun import freeze_time

from accounts.models import User
from .models import Project


@freeze_time("2021-11-14")
class ProjectTests(APITestCase):

    client = APIClient()
    project = None

    name = 'IOT on Blockchain'
    dead_line = datetime.date(2021, 11, 21)
    data = {
        'name': name,
        'dead_line': dead_line,
    }

    def create_user(self):
        username = 'test_user1'
        email = 'test.user1@gmail.com'
        password = '@1234xyz@'
        user_type = 'regular'
        data = {'username': username,
                'email': email,
                'password': password,
                'user_type': user_type,
                }
        return User.objects.create_user(**data)

    def create_project(self):
        project = Project.objects.create(**self.data)
        user = self.create_user()
        project.assigned_to.add(user)
        return project

    def test_create_project_without_api(self):
        """
        Ensure we can create a new project object.
        """
        self.project = self.create_project()
        self.assertEqual(Project.objects.count(), 1)
        self.assertEqual(self.project.name, 'IOT on Blockchain')
        self.assertEqual(self.project.dead_line,
                        datetime.date(2021, 11, 21))
        self.assertFalse(self.project.reached_deadline)
        self.assertEqual(self.project.days_to_deadline, 7)
        # runs successfully

    def test_create_project_with_api(self):
        """
        Ensure we can create a new project object with an
        API call.
        """
        url = 'http://127.0.0.1:8000/api/projects'
        project = self.client.post(url, self.data, format='json')
        # project.data.assigned_to.set(self.create_user())
        pprint(project.__dict__)
        self.assertEqual(Project.objects.count(), 1)
        self.assertEqual(self.project.name, 'IOT on Blockchain')
        self.assertEqual(self.project.slug, 'iot-on-blockchain')
        # does not run successfully (error mentioned in text body)

    def test_delete_project(self):
        """
        We can delete a user
        """
        self.project = self.create_project()
        self.project.delete()
        self.assertEqual(Project.objects.count(), 0)

编辑:添加了序列化程序代码

class ProjectWriteSerializer(serializers.ModelSerializer):
    """
    This serializer is used for CREATE, UPDATE operations on the Project model.
    """

    # We receive list of user ids (ids[int] <= 0) by which we assign
    # users to a project
    assigned_to = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.all(), many=True)

    class Meta:
        model = Project
        fields = ('id', 'name', 'slug', 'assigned_to')

非常感谢任何见解和帮助。

您已经指定了自己的序列化程序字段。因此,它将不再查看 blank=True 部分,并且默认情况下需要序列化程序字段。您可以通过以下方式使这些成为可选的:

class ProjectWriteSerializer(serializers.ModelSerializer):
    assigned_to = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.all(),
        many=True,
        <strong>required=True</strong>
    )

    class Meta:
        model = Project
        fields = ('id', 'name', 'slug', 'assigned_to')