Getting objects before validating data Django REST
Question:
I have to create a new Chat
object using this view:
class ChatListCreateView(ListCreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = ChatSerializer
def get_queryset(self):
data = Chat.objects.filter(
Q(employees=self.request.user) | Q(created_by=self.request.user)).distinct()
return data
The serializer it uses is:
class ChatSerializer(serializers.ModelSerializer):
created_by = SimpleEmployeeSerializer(read_only=True)
employees = SimpleEmployeeSerializer(many=True, read_only=True)
title = serializers.CharField(max_length=255)
def create(self, validated_data):
"""
Creates a new Chat and adds the m2m employees to it
"""
# Create and save the chat
chat = Chat.objects.create(
created_by=self.context['request'].user,
title=validated_data['title'],
)
# Add the employees to the chat
validated_employees = validated_data.pop('employees')
for user_id in validated_employees:
employee = Employee.objects.get(id=user_id)
chat.employees.add(employee)
return chat
My issue is that the SimpleEmployeeSerializer
expects a user
object but I am submitting an array of employees
as such:
{
"title": "fwef",
"employees": [
{
"id": "8"
},
{
"id": "30"
}
]
}
What method can I implement to get the objects from these IDs before validation?
Answers:
Hello David you can take advantage of override the validate
method in the serializer you have to do something like the following:
class ChatSerializer(serializers.ModelSerializer):
created_by = SimpleEmployeeSerializer(read_only=True)
employees = SimpleEmployeeSerializer(many=True, read_only=True)
title = serializers.CharField(max_length=255)
def validate_employees(self, value):
value= transform_ids_in_objects(value)
# handle validation logic here
return value
def create(self, validated_data):
chat = Chat.objects.create(
created_by=self.context['request'].user,
title=validated_data['title'],
)
# ... More code here
return chat
Documentation about validate method Something important about validate
method is that this method is called before create
method.
I think you need to add the employee_ids
field in the serializer.
class ChatSerializer(serializers.ModelSerializer):
created_by = SimpleEmployeeSerializer(read_only=True)
employees = SimpleEmployeeSerializer(many=True, read_only=True)
title = serializers.CharField(max_length=255)
employee_ids = serializers.ListField(
child=serializers.IntegerField(), write_only=True
)
def create(self, validated_data):
"""
Creates a new Chat and adds the m2m employees to it
"""
employee_ids = validated_data.pop("employee_ids")
# Create and save the chat
chat = Chat.objects.create(
created_by=self.context['request'].user,
title=validated_data['title'],
)
# Add the employees to the chat one by one
for user_id in employee_ids:
try:
employee = Employee.objects.get(id=user_id)
chat.employees.add(employee)
except Employee.DoesNotExist:
continue
# Or you can add multiple objects at once
# chat.employees.set(employee_ids)
return chat
And you can upload json data as follows.
{
"title": "fwef",
"employees": [
8, 30
]
}
I have to create a new Chat
object using this view:
class ChatListCreateView(ListCreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = ChatSerializer
def get_queryset(self):
data = Chat.objects.filter(
Q(employees=self.request.user) | Q(created_by=self.request.user)).distinct()
return data
The serializer it uses is:
class ChatSerializer(serializers.ModelSerializer):
created_by = SimpleEmployeeSerializer(read_only=True)
employees = SimpleEmployeeSerializer(many=True, read_only=True)
title = serializers.CharField(max_length=255)
def create(self, validated_data):
"""
Creates a new Chat and adds the m2m employees to it
"""
# Create and save the chat
chat = Chat.objects.create(
created_by=self.context['request'].user,
title=validated_data['title'],
)
# Add the employees to the chat
validated_employees = validated_data.pop('employees')
for user_id in validated_employees:
employee = Employee.objects.get(id=user_id)
chat.employees.add(employee)
return chat
My issue is that the SimpleEmployeeSerializer
expects a user
object but I am submitting an array of employees
as such:
{
"title": "fwef",
"employees": [
{
"id": "8"
},
{
"id": "30"
}
]
}
What method can I implement to get the objects from these IDs before validation?
Hello David you can take advantage of override the validate
method in the serializer you have to do something like the following:
class ChatSerializer(serializers.ModelSerializer):
created_by = SimpleEmployeeSerializer(read_only=True)
employees = SimpleEmployeeSerializer(many=True, read_only=True)
title = serializers.CharField(max_length=255)
def validate_employees(self, value):
value= transform_ids_in_objects(value)
# handle validation logic here
return value
def create(self, validated_data):
chat = Chat.objects.create(
created_by=self.context['request'].user,
title=validated_data['title'],
)
# ... More code here
return chat
Documentation about validate method Something important about validate
method is that this method is called before create
method.
I think you need to add the employee_ids
field in the serializer.
class ChatSerializer(serializers.ModelSerializer):
created_by = SimpleEmployeeSerializer(read_only=True)
employees = SimpleEmployeeSerializer(many=True, read_only=True)
title = serializers.CharField(max_length=255)
employee_ids = serializers.ListField(
child=serializers.IntegerField(), write_only=True
)
def create(self, validated_data):
"""
Creates a new Chat and adds the m2m employees to it
"""
employee_ids = validated_data.pop("employee_ids")
# Create and save the chat
chat = Chat.objects.create(
created_by=self.context['request'].user,
title=validated_data['title'],
)
# Add the employees to the chat one by one
for user_id in employee_ids:
try:
employee = Employee.objects.get(id=user_id)
chat.employees.add(employee)
except Employee.DoesNotExist:
continue
# Or you can add multiple objects at once
# chat.employees.set(employee_ids)
return chat
And you can upload json data as follows.
{
"title": "fwef",
"employees": [
8, 30
]
}