Подсчитайте количество часов, потраченных пользователем в день

У меня есть таблица синхронизации в базе данных. Я хотел посчитать время, потраченное пользователями за день.

Например 2024-03-21, пользователь 1 тратит 6.8 hours, на следующий день он тратит n часов и так далее (['6.8', 'n', ... 'n'])

пользователь дата время в тайм-аут 1 2024-03-21 10:42 утра 12:00 1 2024-03-21 13:10 18:00 1 2024-03-22 13:00 17:47 ... ... ... ...

Это мои модели.py

class Clocking(models.Model):
    user = models.ForeignKey('User', models.DO_NOTHING)
    timein = models.CharField(max_length=15, blank=True, null=True)
    timeout = models.CharField(max_length=15, blank=True, null=True)
    date = models.DateField(null=False)

Я хотел получить список часов, потраченных в день, который был бы мне очень полезен при построении графиков.

Почему это CharField?

willeM_ Van Onsem 06.05.2024 10:27

Самое смешное, что я не знаю. Я просто использовал сопоставление таблиц, потому что эта таблица базы данных уже существует. Это было от предыдущего человека, который это сделал.

zheni 06.05.2024 10:34

Тогда сделай это правильно. В Django есть лучшие типы дат и времени, чем CharField. С ними также будет легче рассчитываться.

Klaus D. 06.05.2024 10:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
84
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

если вы хотите узнать, сколько времени пользователь тратит, вы можете выбрать все записи за одну дату, затем суммировать всех пользователей (timein - timeout), для этого вы можете преобразовать Charfield в объект datetime с помощью встроенной библиотеки или Лучше всего изменить тип поля базы данных на DateTimeField или TimeField.

Ответ принят как подходящий

Пожалуйста, не используйте CharField, чтобы отслеживать. Представьте, что человек заходит now, как это будет работать? Это означает, что вы увеличиваете количество возможных значений, а также увеличиваете использование дискового пространства, хотя последнее, вероятно, не является такой уж большой проблемой.

По сути есть два варианта: работа с TimeFields:

from django.conf import settings


class Clocking(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING)
    date = models.DateField()
    timein = models.TimeField()
    timeout = models.TimeField(null=True)

или работайте с двумя DateTimeField:

from django.conf import settings


class Clocking(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING)
    timein = models.DateTimeField()
    timeout = models.DateTimeField(null=True)

Второй имеет три преимущества: (1) он также легко правильно регистрирует время в даты, когда меняется летнее время. Хотя обычно они меняются в воскресенье около 2:00 ночи, чтобы свести к минимуму объем проблемной бухгалтерии, все же возможно, что это может произойти, например, если человек работает в это время в другом часовом поясе; (2) это также позволяет легко иметь несколько Clocking на одну и ту же дату без дополнительной бухгалтерии; и (3) наконец, это также означает, что у нас может быть Clocking, который продлится больше полуночи. Действительно, представьте, что человек приходит в 9:00 вечера и уходит в 01:00 следующего дня, тогда со старой моделью это будет проблематично, потребуется сначала проверить, не наступит ли время окончания раньше, чем время начала.

Благодаря этому мы можем генерировать статистику для даты, когда элемент начался с:

# second model
from django.db.models import F, Sum
from django.db.models.functions import TruncDate

Clocking.objects.filter(timeout__isnull=False).values(
    date=TruncDate('timein')
).annotate(total=Sum(F('timeout') - F('timein'))).order_by('date')

Примечание. Указывать null=False [Django-doc] необязательно: поля по умолчанию не допускают NULL.


Примечание. Обычно лучше использовать settings.AUTH_USER_MODEL [Django-doc] для ссылки на модель пользователя, чем использовать модель пользователя [Django-doc] напрямую. Для получения дополнительной информации вы можете увидеть со ссылкой на раздел «Модель пользователя» документации.

Я изменил поля на дату и время, на самом деле таким образом легко вычислить время. Спасибо за помощь и разъяснение деталей. Я буду иметь это в виду.

zheni 07.05.2024 04:54

Наконец, как я могу объединить количество часов в одну и ту же дату?

zheni 07.05.2024 05:16

@zhini: обычно вы используете трюк .values(..).annotate(...) в последнем фрагменте кода ответа.

willeM_ Van Onsem 07.05.2024 09:04

Я понял. Мне не следует добавлять order_by в последний фрагмент кода. Это решило мою проблему. Спасибо!

zheni 07.05.2024 10:58

Другие вопросы по теме