[Answer]-Validating Django Forms Via Related Fields

1👍

First of all the conceptualisation is not very clear, for starters should it not be called RegisteredUsers instead of Registration(which is verb and not noun) and if workshop is a many-to-many field it should perhaps be named workshops as it save multiple entries. Apart from that your problem can be solved like this :

1) In clean workshop = self.cleaned_data.get('workshop') , it can (probably is) return multiple values to workshop, lets rename it like this workshops = self.cleaned_data.get('workshops')
2) iterate over the workshops, your query should check for 3 different types of overlap, one when the workshop in question is completely included in one or more other such workshops for this user, second when the workshop starts after one or more workshops but finishes before them, and third when it starts before other workshops but finishes after one or more of them, like this :

from django.db.models import Q
    for workshop in workshops:
        if (workshops.filter(Q(start_time__gte=workshop__start_time),Q(end_time__lte=workshop__end_time) |
                             Q(start_time__lte=workshop__start_time),Q(end_time__gte=workshop__start_time)|
                             Q(start_time__lte=workshop__start_time),Q(end_time__gte=workshop__start_time)).count()>1): # count>1 is used because one of the result of filter will be the same workshop object that we are checking against
            #there is an overlap, put your overlap handling code here
        else:
            #there is no overlap, put your saving the data code here

The only assumption here is that workshops is a queryset and not a list, in case its a list convert it back to queryset by gathering the ids of all workshops in a list and do this to get a queryset of workshops :

workshops = Workshop.objects.filter(pk__in=list_of_ids)

0👍

If you have to check for overlap every time a user registers, it will be a heavy job. Instead what you can do is check for overlap when workshops are getting inserted. Then you can have a overlap table which stores overlapped workshops. That way you can warn user if he’s registering to two workshops which overlap by checking for the same in overlap table.

0👍

You can use lt(less than) or gt(greater than) methods from django queryset. If exists a workshop that start_time > workshop.end_time and start_time = workshop.start_time raise the error.

 def clean(self):
        workshop = self.cleaned_data.get('workshop')
        overlaping = Workshop.objects.filter('start_time__gt'=workshop.end_time,\
                                     'start_time'=workshop.start_time).exists()
        if overlaping:
              raise ValidationError("Workshop times overlap.") 
        return self.cleaned_data 
👤levi

Leave a comment