Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Opening time formset

Context

I need to build a formset to allow opening hours to be set for a week.

Status

Here is my model for opening times:

WEEKDAYS = [
  (1, _("Monday")),
  (2, _("Tuesday")),
  (3, _("Wednesday")),
  (4, _("Thursday")),
  (5, _("Friday")),
  (6, _("Saturday")),
  (7, _("Sunday")),
]

class OpeningHours(models.Model):
    user = models.ForeignKey(User)
    weekday = models.IntegerField(choices=WEEKDAYS)
    from_hour = models.TimeField()
    to_hour = models.TimeField()
    class Meta:
        unique_together = (('user', 'weekday'),)

Here is how I generate a formset for a default week setting

UserOpeningHoursFormSet = formset_factory(UserOpeningHoursForm, extra=0)
hours = [{
        'weekday': day,
        'from_hour': '08:00',
        'to_hour': '18:00',
    } for day in range(1, 8)]
formset = UserOpeningHoursFormSet(initial=hours)

Here is how I get opening hours for the current user

user_hours = request.user.openinghours_set.all()

Question

How can I put the user_hours into my formset ?


Edit

Example, let's say the user already has the hours for Monday and Thursday set in the db, the form should resemble:

weekday: Monday
from_hour: '09:00' # user_set
to_hour: '19:00' # user_set

weekday: Tuesday
from_hour: # default initial value
to_hour: # default initial value

weekday: Wednesday
from_hour: # default initial value
to_hour: # default initial value

weekday: Thursday
from_hour: '13:00' # user_set
to_hour: '15:00' # user_set

weekday: Friday
from_hour: # default initial value
to_hour: # default initial value

weekday: Saturday
from_hour: # default initial value
to_hour: # default initial value
like image 468
Pierre de LESPINAY Avatar asked Apr 18 '26 18:04

Pierre de LESPINAY


1 Answers

Expanding on @Rohan's answer:

I don't think modelformset is neccessary, just construct the hours like this

hours = [
    {'weekday': day, 'from_hour': '08:00', 'to_hour': '18:00'} 
    for day in range(1, 8) if not any(request.user.openinghours_set.filter(weekday=day))
    else
    {'weekday': day, 'from_hour': request.user.openinghours_set.filter(weekday=day).from_hour,
     'to_hour': request.user.openinghours_set.filter(weekday=day).to_hour}
]

Obviously, this is inefficient as it constructs one or three queryset(s) for each day, so rewriting it like this:

hours = []

openinghours_set = list(request.user.openinghours_set.all())
for day in range(1, 8):
    for openinghours in openinghours_set:
        if openinghours.weekday == day:
            hours.append({ fill from *openinghours* })
            break
    else:
        hours.append({ fill with default values })
like image 106
XORcist Avatar answered Apr 21 '26 08:04

XORcist



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!