mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-05-20 17:28:55 +00:00
0d621b68e0
Accessing many-to-many relations before saving is no longer allowed. Reorder all operations consistently: 1. Validations 2. Modify own fields 3. Perform save by calling super().save() 4. Modify related objects and clear caches Especially clearing caches should be done after actually saving, otherwise the old data can be re-added immediately by another request before the new data is written.
77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
""" progress in a book """
|
|
from django.core import validators
|
|
from django.core.cache import cache
|
|
from django.db import models
|
|
from django.db.models import F, Q
|
|
|
|
from .base_model import BookWyrmModel
|
|
|
|
|
|
class ProgressMode(models.TextChoices):
|
|
"""types of progress available"""
|
|
|
|
PAGE = "PG", "page"
|
|
PERCENT = "PCT", "percent"
|
|
|
|
|
|
class ReadThrough(BookWyrmModel):
|
|
"""Store a read through a book in the database."""
|
|
|
|
user = models.ForeignKey("User", on_delete=models.PROTECT)
|
|
book = models.ForeignKey("Edition", on_delete=models.PROTECT)
|
|
progress = models.IntegerField(
|
|
validators=[validators.MinValueValidator(0)], null=True, blank=True
|
|
)
|
|
progress_mode = models.CharField(
|
|
max_length=3, choices=ProgressMode.choices, default=ProgressMode.PAGE
|
|
)
|
|
start_date = models.DateTimeField(blank=True, null=True)
|
|
finish_date = models.DateTimeField(blank=True, null=True)
|
|
stopped_date = models.DateTimeField(blank=True, null=True)
|
|
is_active = models.BooleanField(default=True)
|
|
|
|
def save(self, *args, **kwargs):
|
|
"""update user active time"""
|
|
# an active readthrough must have an unset finish date
|
|
if self.finish_date or self.stopped_date:
|
|
self.is_active = False
|
|
|
|
super().save(*args, **kwargs)
|
|
|
|
cache.delete(f"latest_read_through-{self.user_id}-{self.book_id}")
|
|
self.user.update_active_date()
|
|
|
|
def create_update(self):
|
|
"""add update to the readthrough"""
|
|
if self.progress:
|
|
return self.progressupdate_set.create(
|
|
user=self.user, progress=self.progress, mode=self.progress_mode
|
|
)
|
|
return None
|
|
|
|
class Meta:
|
|
"""Don't let readthroughs end before they start"""
|
|
|
|
constraints = [
|
|
models.CheckConstraint(
|
|
check=Q(finish_date__gte=F("start_date")), name="chronology"
|
|
)
|
|
]
|
|
ordering = ("-start_date",)
|
|
|
|
|
|
class ProgressUpdate(BookWyrmModel):
|
|
"""Store progress through a book in the database."""
|
|
|
|
user = models.ForeignKey("User", on_delete=models.PROTECT)
|
|
readthrough = models.ForeignKey("ReadThrough", on_delete=models.CASCADE)
|
|
progress = models.IntegerField(validators=[validators.MinValueValidator(0)])
|
|
mode = models.CharField(
|
|
max_length=3, choices=ProgressMode.choices, default=ProgressMode.PAGE
|
|
)
|
|
|
|
def save(self, *args, **kwargs):
|
|
"""update user active time"""
|
|
self.user.update_active_date()
|
|
super().save(*args, **kwargs)
|