Postman показывает "This field is required" только для поля ManyToMany в django
У меня есть 2 модели - модуль и комната. Модуль может иметь ноль или несколько комнат, а комната может быть добавлена в несколько модулей. Таким образом, между ними существует простое отношение "многие-ко-многим".
Когда я использую post request, raw-data работает, но не form-data.
module/models.py -
class Module(models.Model):
module_id = models.AutoField(primary_key=True)
title = models.CharField(max_length=100)
desc = models.TextField()
room_list = models.CharField(max_length = 100, blank=True)
rooms = models.ManyToManyField(Rooms, blank=True)
rooms/models.py -
class Rooms(models.Model):
room_id = models.AutoField(primary_key=True)
title = models.CharField(max_length=100)
level = models.CharField(max_length=100)
desc = models.TextField()
module/serializers.py -
class ModuleSerializer(serializers.ModelSerializer):
rooms = RoomSerializer(many=True)
class Meta:
model = Module
fields = '__all__'
def create(self, validated_data):
rooms_data = validated_data.pop('rooms')
module = Module.objects.create(**validated_data)
for data in rooms_data:
room = Rooms.objects.get(**data)
module.rooms.add(room)
return module
def update(self, instance, validated_data):
# Updating rooms
rooms_data = validated_data.get('rooms')
instance.rooms.clear()
for room_data in rooms_data:
room = Rooms.objects.get(**room_data)
instance.rooms.add(room)
# Updating other fields
fields = [
'title',
'desc',
'thumbnail',
'is_deleted',
]
for field in fields:
setattr(instance, field, validated_data[field])
instance.save()
return instance
rooms/serialier.py -
class RoomSerialize(serializers.ModelSerializer):
room_id = serializers.IntegerField()
class Meta:
model = Rooms
fields = "__all__"
module/views.py -
class add_module(APIView):
def post(self, request, format=None):
# Adding the rooms to module from room_list
new_request = request.data.copy()
room_list=[]
if 'room_list' in new_request:
room_list_data = list(new_request['room_list'].split(" "))
for room in room_list_data:
room_object = Rooms.objects.get(room_id=room)
room_serializer = RoomSerializer(room_object)
room_list.append(room_serializer.data)
new_request.update({'rooms':room_list})
# creating the module
module_serializer = ModuleSerializer(data=new_request)
if module_serializer.is_valid():
module_serializer.save()
return Response(module_serializer.data['module_id'])
return Response(module_serializer.errors)
Тело запроса POST для обновления модуля в POSTMAN -
{
"module_id": 2,
"room_list": "1 2",
"title": "4",
"desc": "22",
}
Обратите внимание, что при приеме ввода поля ManyToMany - "rooms", я принимаю строку "room_list" в качестве ввода, которая содержит все room_ids, которые должны быть включены. Это прекрасно работает, когда я принимаю входные данные как raw-data в postman, но когда я использую form-data, это показывает
{
"rooms": [
"This field is required."
]
}
Что делать?
Прежде всего, поля сериализатора с (many=True) создают вложенные объекты.
Если вы вводите данные с Rooms
как уже сериализованные, то это означает, что вы создаете другие экземпляры Rooms
. Это будет показано частью if module_serializer.is_valid():
. Поэтому, если вы хотите реализовать просто ссылку уже инстанцированного Rooms
на Module
, то лучше сделать это в виде списка с первичным ключом.
Вот мои примеры кодов.
class ModuleSerializer(serializers.ModelSerializer):
rooms = RoomSerializer(many=True, read_only=True)
def create(self, validated_data):
rooms_data = validated_data['room_list']
module = Module.objects.create(**validated_data)
for data in rooms_data.split(' '):
room = Rooms.objects.get(room_id=data)
module.rooms.add(room)
return module
def update(self, instance, validated_data):
# Updating rooms
rooms_data = validated_data.get('rooms')
instance.rooms.clear()
for room_data in rooms_data:
room = Rooms.objects.get(**room_data)
instance.rooms.add(room)
# Updating other fields
fields = [
'title',
'desc',
'thumbnail',
'is_deleted',
]
for field in fields:
setattr(instance, field, validated_data[field])
instance.save()
return instance
class Meta:
model = Module
fields = '__all__'
class AddModule(APIView):
def post(self, request, format=None):
# creating the module
module_serializer = ModuleSerializer(data=request.data)
if module_serializer.is_valid():
module_serializer.save()
return Response(module_serializer.data['module_id'])
return Response(module_serializer.errors)
Все остальные детали совпадают с вашими. Независимо от того, отправлены ли данные формой-данные или необработанные данные в формате json, результаты такие же, как показано ниже.