I need help with a custom model method in Django

I am developing a web application in Django that manages work on a repeat weekly basis. These are the models that I have come up with so far. Hosts should be able to schedule a few weekly days and times. Thus, the hostess of linen can be on Sunday at 8:00 and on Wednesday from 5:30 in the evening. First, I want to confirm that the models below are the best way to introduce this. Secondly, I got a little confused about model relationships and user model methods. Since these responsibilities are on a repeated basis, I need to be able to check whether this week was a completed version. Since this is row-level functionality, will this be a model method right? Based on the models below, how would I test this? It makes me scratch my head.

models.py:

  from django.db import models
 from datetime import date

 class ChoreManager (models.Manager):
     def by_day (self, day_name):
         return self.filter (scheduledday__day_name = day_name)

     def today (self):
         todays_day_name = date.today (). strftime ('% A')
         return self.filter (scheduledday__day_name = todays_day_name)

 class Chore (models.Model):
     objects = ChoreManager ()
     name = models.CharField (max_length = 50)
     notes = models.TextField ()

     class Meta:
         ordering = ['scheduledday__time']

 class ScheduledDay (models.Model):
     day_name = models.CharField (max_length = 8)
     time = models.TimeField ()
     chore = models.ForeignKey ('Chore')

 class CompletedEvent (models.Model):
     date_completed = DateTimeField (auto_now_add = True)
     chore = models.ForeignKey ('Chore')
+4
source share
2 answers

Then you just need to:

monday_of_week = some_date - datetime.timedetla(days=some_date.weekday()) end_of_week = date + datetime.timedelta(days=7) chore = Chore.objects.get(name='The chore your looking for') ScheduledDay.objects.filter(completed_date__gte=monday_of_week, completed_date__lt=end_of_week, chore=chore) 
+2
source

Option (and faster) - use bitmasks!

Think about the days of the week when you want the chore to be repeated as a binary number - a bit for each day. For example, if you want the chorus to be repeated every Tuesday, Friday, and Sunday, you get the binary number 1010010 (or 82 in decimal):

 SSFTWTM 1 0 1 0 0 1 0 = 1010010 

Days are reversed to illustrate.

And to check if you need to do the work today, just enter the number of this day and do & :

 from datetime import datetime as dt if dt.today().weekday() & 0b1010100: print("Do chores!") 


Models

Your .py models would look something like this:

 from django.contrib.auth.models import User from django.db import models from django.utils.functional import cached_property class Chore(models.Model): name = models.CharField(max_length=128) notes = models.TextField() class ChoreUser(models.Model): chore_detail = models.ForeignKey('ChoreDetail') user = models.ForeignKey('ChoreDetail') completed_time = models.DateTimeField(null=True, blank=True) class ChoreDetail(models.Model): chore = models.ForeignKey('Chore') chore_users = models.ManyToManyField('User', through=ChoreUser) time = models.DateTimeField() date_begin = models.DateField() date_end = models.DateField() schedule = models.IntegerField(help_text="Bitmask of Weekdays") @cached_property def happens_today(self): return bool(dt.today().weekday() & self.weekly_schedule) 

This scheme has an M2M relationship between the User and the Hourly Schedule. Thus, you can expand your idea, for example, by recording the duration of work (if you want) or even many users participating in the same work.


And to answer your question, if you want a list of completed events this week, you could put this in the model manager for ChoreUser :

 from datetime import datetime as dt, timedelta week_start = dt.today() - timedelta(days=dt.weekday()) week_end = week_start + timedelta(days=6) chore_users = ChoreUser.objects.filter(completed_time__range=(week_start, week_end)) 


Now you have all the necessary information in one DB call:

 user = chore_users[0].user time = chore_users[0].chore_detail.time name = chore_users[0].chore_detail.chore.name happens_today = chore_users[0].chore_detail.happens_today 

You can also easily get all completed tasks for the user:

 some_user.choreuser_set.filter(completed_time__range=(week_start, week_end)) 
+1
source

Source: https://habr.com/ru/post/1334291/


All Articles