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)
Вернуться на верх