Django: поле m2m может быть не пустым
Студенты могут быть распределены по многим группам.
- Один студент может быть распределен во многие группы
- В одной группе может быть много студентов .
С помощью приведенного ниже кода я могу
- Создать студента, не имеющего группы или назначенного в некоторые группы.
- Я могу изменить все с успехом, кроме...
Кроме того, я не могу удалить все группы, назначенные студенту. Я предполагаю, что какой-то студент может отписаться от всех групп. Но django это не нравится и выдает error:
{'groups': [ErrorDetail(string='This list may not be empty.', code='empty')]}
Код:
Модели:
class Group(models.Model):
group_name = models.CharField(max_length=30, unique=True, null=True, blank=True)
class Student(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
groups = models.ManyToManyField(Group)
Создать студента:
new_student = Student.objects.create(
first_name = request.data["first_name"],
last_name = request.data["last_name"],
)
groups_id = request.data["group_id"]
if(groups_id):
for group_id in groups_id:
new_student.groups.add(group_id)
Сменить студента:
def change_student(request, id):
student_to_change = Student.objects.get(id=id)
serializer = StudentSerializer(
instance=student_to_change,
data={
'first_name': request.data["first_name"],
'last_name': request.data["last_name"],
'groups': request.data["groups"],
}
)
if serializer.is_valid():
serializer.save()
А когда я пытаюсь выполнить change_student с, например: request.data :
{'id': 16, 'first_name': 'John', 'last_name': 'Smith', 'groups': []}
Я получаю
{'groups': [ErrorDetail(string='This list may not be empty.', code='empty')]}
error
И сериализаторы:
class GroupSerializer(ModelSerializer):
class Meta:
model = Group
fields = '__all__'
class StudentSerializer(ModelSerializer):
class Meta:
model = Student
fields = '__all__'
Я думаю, что вы можете установить два поля для чтения и записи groups
атрибута.
class StudentSerializer(ModelSerializer):
groups = GroupSerializer(many = True, read_only = True)
group_ids = serializers.ListField(
child = serializers.IntegerField(), write_only = True
)
class Meta:
model = Student
fields = '__all__'
extra_fields = ['group_ids']
def create(self, validated_data):
group_ids = validated_data.pop('group_ids')
student = Student.objects.create(**validated_data)
student.groups.set(group_ids)
return student
def update(self, instance, validated_data):
group_ids = validated_data.pop('group_ids')
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.groups.set(group_ids)
instance.save()
return instance
А полезная нагрузка должна быть такой:
{'id': 16, 'first_name': 'John', 'last_name': 'Smith', 'group_ids': []}
Я добавил код для поля groups
в сериализатор. Поэтому вам не нужно писать логику для сохранения этого поля в представлении.
Я обнаружил, что проблема была в моделях. Внутри класса Student должно быть "blank=True" и теперь при создании объекта студента - поле groups может быть отправлено как пустой список
class Student(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
groups = models.ManyToManyField(Group, blank=True)