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')
我有以下模型项目:
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')