Редактирование поля "многие ко многим" в Django
У меня проблема с редактированием страницы в моем коде. В принципе, у меня есть страница, на которой есть несколько полей выбора, где я могу выбрать студентов. Но у меня проблема с пониманием того, как удалить определенного студента, если мне нужно отредактировать эту страницу. Позвольте мне быть более ясным с некоторым кодом.
models.py
class TheorySyllabus(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
subject_duration = models.ManyToManyField(
SubjectDuration, related_name='theory_syllabus')
course_type = models.ForeignKey(
CourseType, on_delete=models.DO_NOTHING, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'Theory Syllabus'
class TheoryCourse(models.Model):
name = models.CharField(max_length=100)
student = models.ManyToManyField(Student, related_name='theory_courses')
theory_syllabus = models.ForeignKey(
TheorySyllabus, on_delete=models.DO_NOTHING, null=True, blank=True)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
views.py
def edit_theory_course(request, pk):
theory_course = TheoryCourse.objects.get(id=pk)
student_obj = theory_course.student.all()
theory_syllabus = TheorySyllabus.objects.all()
students = Student.objects.filter(is_active=True).order_by('last_name')
context = {
'theory_course': theory_course,
'theory_syllabus': theory_syllabus,
'students': students,
'student_obj': student_obj,
}
if request.method == 'POST':
course_name = request.POST.get('course_name')
student = request.POST.getlist('student')
syllabus = request.POST.get('syllabus')
try:
theory_course.name = course_name
theory_course.theory_syllabus_id = syllabus
theory_course.save()
for stud in student:
theory_course.student.add(stud)
theory_course.save()
messages.success(request, "Theoretical Course Edited")
return HttpResponseRedirect(reverse('theory:course_list'))
except:
messages.error(request, "Failed to Edit Theoretical Course")
return HttpResponseRedirect(reverse('theory:edit_theory_course', kwargs={'pk': pk}))
return render(request, 'theory/edit_theory_course.html', context)
Я знаю, что в основном, то, что мне нужно сделать, это в представлении разместить оператор if для сравнения двух списков и удаления (при необходимости) значения, которое больше не является частью списка записей. Проблема в том, что я понятия не имею, как разместить эту логику. Любая помощь будет высоко оценена. Большое спасибо
Думаю, вы можете заменить весь список студентов сразу, выполнив theory_course.student.set([list_of_student_pks])
Очень чистый и простой способ достичь этого - сделать запрос для всех текущих студентов (что вам даже не нужно делать, поскольку это уже есть в theory_course), а затем просто получить разницу между студентами в этом запросе и представленными студентами. Это даст вам удаленных студентов, которых вы можете перебрать и удалить.
current_students = theory_course.students
selected_students = Student.objects.filter(pk__in=student)
removed_students = current_students.difference(selected_students)
for s in removed_students:
s.delete()
Однако есть возможность установить все идентификаторы сразу, используя метод объекта set(), но иметь список удаленных пользователей, чтобы вы могли внести необходимые изменения (например, отправить электронную почту), гораздо лучше, исходя из моего опыта.