简体   繁体   中英

(Django) UpdateView query only working sometimes

I have a school management app that has a feature to drop a student or teacher from a particular course. The problem is it only works with some users and not others.

In my urls.py, I have the following:

path('profile/<int:pk>/drop_session/<int:pk2>', user_views.DropStudentFromSession.as_view(), name='drop_student_session'),

Then in my views.py, this is my CBV for dropping a student:

class DropStudentFromSession(UserPassesTestMixin, UpdateView):
model = Session
template_name = 'users/drop_student_session.html'
fields = []

def test_func(self):
    return True if self.request.user.groups.filter(name='Admin').count() > 0 else False

def handle_no_permission(self):
    return redirect('denied')

def form_valid(self, form):
    course = get_object_or_404(Session, pk=self.kwargs.get('pk2'))
    user = get_object_or_404(User, pk=self.kwargs.get('pk'))
    user.student.enrolled_courses.remove(course)
    user.save()
    return super().form_valid(form)

def get_success_url(self):
    user = get_object_or_404(User, pk=self.kwargs.get('pk'))
    messages.success(self.request, 'Student withdrawn from session.')
    return reverse('user_profile', kwargs={'pk': user.id})

So the in the form_valid method, it grabs the user's PK and the session's PK so it can successfully remove it from the student's enrolled courses. But it seemed to only work with my one test user that has a PK=2, but not the others.

What am I missing here?

EDIT, here's the models for Michael Lindsay:

class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
enrolled_courses = models.ManyToManyField(Session, blank=True)
student_id_number = models.IntegerField(null=True, blank=True)

def __str__(self):
    return f'{self.user.last_name}, {self.user.first_name}'

And here's the Session model:

class Session(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
course_date_start = models.DateField()
course_date_end = models.DateField()

def session_id(self):
    new_session_date = self.course_date_start.strftime('%Y')
    return f'{new_session_date}{self.course.number}{self.pk}'

def __str__(self):
    return f'{self.course.number} - {self.course.title} - {self.session_id()}'

Thanks to @MichaelLindsay, I used a RedirectView instead so now the code looks like this:

class DropSessionStudent(UserPassesTestMixin, RedirectView):
permanent = False
query_string = True
pattern_name = 'user_profile'

def test_func(self):
    return True if self.request.user.groups.filter(name='Admin').count() > 0 else False

def handle_no_permission(self):
    return redirect('denied')

def get_redirect_url(self, *args, **kwargs):
    user = get_object_or_404(User, pk=self.kwargs.get('pk'))
    course = get_object_or_404(Session, pk=self.kwargs.get('pk2'))
    user.student.enrolled_courses.remove(course)
    user.save()
    messages.success(self.request, 'Session successfully withdrawn from the student.')
    return reverse('user_profile', kwargs={'pk': user.id})

The only downside to this is that a misclick will drop a student or teacher from that class, so I need to add a confirm dialog, but now it's working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM