T
T
Timofey Bulgarian2019-09-24 23:51:19
Django
Timofey Bulgarian, 2019-09-24 23:51:19

How to describe the storage of working hours in the database?

It is necessary to describe a model that will store the company's working hours for each day of the week. Including a serializer to it and a viewset. At the same time, it is necessary that in when it is displayed and accepted approximately in this format (non-working ones are simply not displayed):

working_hours: {
    monday: [12:30, 12:40],
    wednesday: [18:40, 19:40]
}

I myself described the model, where for each day of the week there is a field whether it is a working day, start time, end time. Plus, for the output, I made a property field that collects their output as in the example. But there were difficulties with the serializer, which would receive data in this form and save everything in its fields.
The code cannot be attached.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
J
JRazor, 2019-09-25
@JRazor

The model is simple - the day of the week, the beginning of the working day, the end of the working day.
Read the documentation for DRF, there is nothing complicated there. Redefining the save, update methods in serializers and other things.

W
werevolff, 2019-09-25
@werevolff

1. Business hours are a str data type and not a datetime! Why? Because Datetime returns a specific date anyway. How to imagine it:

start_time: str = '12:20'
end_time: str = '16:00'

There is also TimeField, but then it will be necessary to declare format=
2 in the field. There are several options for writing this data to the model. The easiest one is via Choices:
class WorkDay(models.Model):
    DAYS_OF_WEEK = (
        (1, _('Monday')),
        (2, _('Tuesday')),
        (3, _('Wednesday')),
        (4, _('Thursday')),
        (5, _('Friday')),
        (6, _('Saturday')),
        (7, _('Sunday')),
    )
    DAY_TYPES = (
        ('weekday', _('weekday')),
        ('holiday', _('holiday')),
    )
    day_of_the_week = models.PositiveIntegerField(
        verbose_name=_('day of the week'),
        choices=DAYS_OF_WEEK
    )
    start_time = models.CharField(
        verbose_name=_('start time'),
        max_length=5
    )
    end_time = models.CharField(
        verbose_name=_('end time'),
        max_length=5
    )
    day_type = models.CharField(
        verbose_name=_('day type'),
        max_length=255,
        choices=DAY_TYPES
    )

3. We may need to record several pairs of working hours per business day. In this case, the most correct way I would consider using ArrayField or ListField
from django.contrib.postgres.fields import ArrayField

class WorkDay(models.Model):
    DAYS_OF_WEEK = (
        (1, _('Monday')),
        (2, _('Tuesday')),
        (3, _('Wednesday')),
        (4, _('Thursday')),
        (5, _('Friday')),
        (6, _('Saturday')),
        (7, _('Sunday')),
    )
    DAY_TYPES = (
        ('weekday', _('weekday')),
        ('holiday', _('holiday')),
    )
    day_of_the_week = models.PositiveIntegerField(
        verbose_name=_('day of the week'),
        choices=DAYS_OF_WEEK
    )
    working_hours = ArrayField(
        ArrayField(
            models.CharField(
                max_length=5
            ),
            size=2
        ),
        verbose_name=_('working hours')
    )
    day_type = models.CharField(
        verbose_name=_('day type'),
        max_length=255,
        choices=DAY_TYPES
    )

4. Also, we can use JSONField ( MySQL or PostgreSQL )
from django.contrib.postgres.fields import JSONField

class WorkGraph(models.Model):
    working_graph = JSONField(
        verbose_name=_('working graph'),
        default={
            'monday': {
                'hours': ['12:20', '16:00'],
                'day_type': 'weekday'
            }
        }
    )

I would prefer the ArrayField option.
ArrayField, like JSONField, is supported by DRF and represents data as Python arrays that can be processed through validate.
With this approach, the front takes care of building the UI, where the user simply selects the hours and minutes on the form and adds them. JS builds an array based on the form and passes it to DRF.
And as a bonus, we use validation for Django and DRF fields :
import re
from django.core.exceptions import ValidationError
from typing import NoReturn

def validate_working_hours(
        value: str
) -> NoReturn:
    m = re.match(
        r'^(?P<hours>\d{2}):(?P<minutes>\d{2})$',
        value
    )
    if m is None:
        raise ValidationError('please, use format HH:mm')
    else:
        hours = int(
            m.group('hours')
        )
        if hours > 23:
            raise ValidationError('hours is a value from 0 to 23')
        minutes = int(
            m.group('minutes')
        )
        if minutes > 59:
            raise ValidationError('minutes is a value from 0 to 59')

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question