Как вычислить полосу текущего дня в Django?
Я хотел бы вычислять каждый раз, когда создается или обновляется ClassAttempt со статусом "завершен".
class ClassAttempt(models.Model):
user = models.ForeignKey(to=User,on_delete= models.PROTECT, null=True)
related_class = models.ForeignKey(to=Class, related_name='attempt', on_delete= models.PROTECT, null=True)
collected_xp = models.IntegerField(null=True, blank=True, default=0)
status = models.CharField(
verbose_name='status',
max_length=20,
choices=(
('no-completed', 'no-completed'),
('completed', 'completed'),
),
default='no-completed'
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Я не уверен, что понял ваш вопрос, но сигнал post_save (https://docs.djangoproject.com/en/4.1/ref/signals/#post-save) позволяет вам запускать некоторый код python каждый раз, когда метод .save() вызывается на определенной модели. (Также работает на model.objects.create())
.
Вы могли бы проверять статус сохраненного экземпляра и увеличивать какой-то счетчик в приемнике сигнала. (хотя из вашего сообщения неясно, где будет храниться этот счетчик)
Большое спасибо, у меня есть еще один вопрос, так как здесь я отслеживаю использованную дневную полосу и нет модели User, как именно это сделать. То есть приемник, который я знаю, срабатывает каждый раз, когда ClassAttempt обновляется или создается, но нам нужно отслеживать на другой модели.
class UserLeaderboardTracking(models.Model):
user = models.ForeignKey(to=User, related_name='user_leaderboard', on_delete=models.CASCADE, null=True)
xp_value = models.PositiveIntegerField(null=True, blank=True)
day_streak = models.PositiveIntegerField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"id : {self.pk} Username : {self.user.username}"
Это должно работать, я думаю, я подтвержу после некоторых испытаний.
def post_save_class_attempt_streak_handler(sender, instance: ClassAttempt, **kargs):
user: User = instance.user
last_attempt: Optional[ClassAttempt] = ClassAttempt.objects.filter(user=instance.user).exclude(
id=instance.id).order_by("-updated_at").first()
if not last_attempt:
# first attempt
UserStatisticStatus.day_streak = 1
user.save()
return
today: date = timezone.now().date()
last_attempt_date = last_attempt.updated_at.date()
if last_attempt_date == today - timedelta(days=1):
# last attempt was yesterday
UserStatisticStatus.day_streak += 1
user.save()
elif last_attempt_date != today:
# last attempt was before yesterday
UserStatisticStatus.day_streak = 1
user.save()
Это работает для меня
def post_save_class_attempt_streak_handler(sender, instance, *args, **kwargs):
last_attempt = ClassAttempt.objects.filter(user=instance.user).exclude(
id=instance.id).order_by("-updated_at").first()
if not last_attempt:
# first attempt
UserStatisticStatus.objects.update(day_streak = 1)
return
today: date = timezone.now().date()
last_attempt_date = last_attempt.updated_at.date()
if last_attempt_date == today - timedelta(days=1):
# last attempt was yesterday
UserStatisticStatus.objects.update(day_streak =+ 1)
elif last_attempt_date != today:
# last attempt was before yesterday
UserStatisticStatus.objects.update(day_streak = 1)