Get time slots based on multiple workshops
You can simplify the creation of DAY_CHOICES using the calendar module:

DAY_CHOICES = tuple(enumerate(calendar.day_name))


this has the advantage of using the right locale, if need be.



You can reduce going back and forth between Python and your SQL backend using prefetching of objects, instead of querying each time you need something. Django offers the prefetch_related operation:

workshops = Workshop.objects.prefetch_related(
    Prefetch(
        'workshopholiday_set',
        queryset=WorkshopHoliday.objects.filter(
            holiday_date__ge=start_date,
            holiday_date__le=start_date + timezone.timedelta(days=7),
            active=True),
        to_attr='holidays_for_the_week'))


Where start_date is timezone.now().date(). This way, you get a list of every WorkshopHoliday for the upcoming week associated to the current workshop into workshop.holidays_for_the_week. You can test if the current date is in there with:

if curdate in {h.holiday_date for h in workshop.holidays_for_the_week}:
    continue


I would also advise to exchange the two for loops so you don't compute the set of holiday dates seven time for the same workshop.



curdate_dict is not necessary. You can replace

curdate_dict = {'start_time': None, 'end_time': None}


by

start_time, end_time = None, None


and remove all curdate_dict.get(…) and curdate_dict[…] = …. You just need to slots[curdate] = {'start_time': start_time, 'end_time': end_time} then, which will improve the memory management as well.



current_time.replace(hour=0, minute=0, second=0)


does nothing: the replace method returns a new datetime instance and since you’re not assigning it, you’re just wasting time.



for i in range(1, 7):


First of, i is never used: you should write _ instead to indicate that. Second, range(1, 7) produces 6 values. So you will perform your computations for today and the 5 next days. If you wished to compute your hours for a whole week, you should have written

for _ in range(7):


instead.

I also advise you to get the "counter" near that line. This is so the reader can grasp your intent more easily:

def get_slots():
    starting_time = timezone.now()
    start_date = starting_time.date()
    workshops = Workshop.objects.prefetch_related(
        Prefetch(
            'workshopholiday_set',
            queryset=WorkshopHoliday.objects.filter(
                holiday_date__ge=start_date,
                holiday_date__le=start_date + timezone.timedelta(days=7),
                active=True),
            to_attr='holidays_for_the_week'))
    slots = {}
    for day in range(7):
        current_time = starting_time + timezone.timedelta(days=day)
        …