I have the following model Project:
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)
If I need to create a new project, all I need to do is supply the name
alone. This works for both the Admin dashboard and DRF APIVIEW. But when I try to test the functionality with DRF with an API call, I get the error: [b'{"assigned_to":["This field is required."]}']
Although the field is not required.
My test code below
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 = '[email protected]'
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)
Edit: Added serializer code
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')
Any insights and help is very appreciated.
CodePudding user response:
You have specified your own serializer field. As a result, it will no longer look at the blank=True
part, and by default serializer fields are required. You can make these optional with:
class ProjectWriteSerializer(serializers.ModelSerializer):
assigned_to = serializers.PrimaryKeyRelatedField(
queryset=User.objects.all(),
many=True,
required=True
)
class Meta:
model = Project
fields = ('id', 'name', 'slug', 'assigned_to')