Skip to content

Commit

Permalink
Modify update_fields in save() when modifying objects
Browse files Browse the repository at this point in the history
  • Loading branch information
Minnozz committed Apr 25, 2024
1 parent a6c2ce1 commit e7f95ef
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 38 deletions.
6 changes: 3 additions & 3 deletions bookwyrm/models/author.py
@@ -1,7 +1,7 @@
""" database schema for info about authors """

import re
from typing import Tuple, Any
from typing import Any

from django.db import models
from django.contrib.postgres.indexes import GinIndex
Expand Down Expand Up @@ -45,9 +45,9 @@ class Author(BookDataModel):
)
bio = fields.HtmlField(null=True, blank=True)

def save(self, *args: Tuple[Any, ...], **kwargs: dict[str, Any]) -> None:
def save(self, *args: Any, **kwargs: Any) -> None:
"""normalize isni format"""
if self.isni:
if self.isni is not None:
self.isni = re.sub(r"\s", "", self.isni)

super().save(*args, **kwargs)
Expand Down
38 changes: 27 additions & 11 deletions bookwyrm/models/book.py
Expand Up @@ -2,7 +2,7 @@

from itertools import chain
import re
from typing import Any, Dict
from typing import Any, Dict, Optional, Iterable
from typing_extensions import Self

from django.contrib.postgres.search import SearchVectorField
Expand All @@ -27,7 +27,7 @@
ENABLE_PREVIEW_IMAGES,
ENABLE_THUMBNAIL_GENERATION,
)
from bookwyrm.utils.db import format_trigger
from bookwyrm.utils.db import format_trigger, add_update_fields

from .activitypub_mixin import OrderedCollectionPageMixin, ObjectMixin
from .base_model import BookWyrmModel
Expand Down Expand Up @@ -96,14 +96,19 @@ class Meta:

abstract = True

def save(self, *args: Any, **kwargs: Any) -> None:
def save(
self, *args: Any, update_fields: Optional[Iterable[str]] = None, **kwargs: Any
) -> None:
"""ensure that the remote_id is within this instance"""
if self.id:
self.remote_id = self.get_remote_id()
update_fields = add_update_fields(update_fields, "remote_id")
else:
self.origin_id = self.remote_id
self.remote_id = None
super().save(*args, **kwargs)
update_fields = add_update_fields(update_fields, "origin_id", "remote_id")

super().save(*args, update_fields=update_fields, **kwargs)

# pylint: disable=arguments-differ
def broadcast(self, activity, sender, software="bookwyrm", **kwargs):
Expand Down Expand Up @@ -510,28 +515,39 @@ def get_rank(self):
# max rank is 9
return rank

def save(self, *args: Any, **kwargs: Any) -> None:
def save(
self, *args: Any, update_fields: Optional[Iterable[str]] = None, **kwargs: Any
) -> None:
"""set some fields on the edition object"""
# calculate isbn 10/13
if self.isbn_13 and self.isbn_13[:3] == "978" and not self.isbn_10:
if (
self.isbn_10 is None
and self.isbn_13 is not None
and self.isbn_13[:3] == "978"
):
self.isbn_10 = isbn_13_to_10(self.isbn_13)
if self.isbn_10 and not self.isbn_13:
update_fields = add_update_fields(update_fields, "isbn_10")
if self.isbn_13 is None and self.isbn_10 is not None:
self.isbn_13 = isbn_10_to_13(self.isbn_10)
update_fields = add_update_fields(update_fields, "isbn_13")

# normalize isbn format
if self.isbn_10:
if self.isbn_10 is not None:
self.isbn_10 = normalize_isbn(self.isbn_10)
if self.isbn_13:
if self.isbn_13 is not None:
self.isbn_13 = normalize_isbn(self.isbn_13)

# set rank
self.edition_rank = self.get_rank()
if (new := self.get_rank()) != self.edition_rank:
self.edition_rank = new
update_fields = add_update_fields(update_fields, "edition_rank")

# Create sort title by removing articles from title
if self.sort_title in [None, ""]:
self.sort_title = self.guess_sort_title()
update_fields = add_update_fields(update_fields, "sort_title")

super().save(*args, **kwargs)
super().save(*args, update_fields=update_fields, **kwargs)

# clear author cache
if self.id:
Expand Down
14 changes: 10 additions & 4 deletions bookwyrm/models/link.py
@@ -1,11 +1,13 @@
""" outlink data """
from typing import Optional, Iterable
from urllib.parse import urlparse

from django.core.exceptions import PermissionDenied
from django.db import models
from django.utils.translation import gettext_lazy as _

from bookwyrm import activitypub
from bookwyrm.utils.db import add_update_fields
from .activitypub_mixin import ActivitypubMixin
from .base_model import BookWyrmModel
from . import fields
Expand Down Expand Up @@ -34,17 +36,19 @@ def name(self):
"""link name via the associated domain"""
return self.domain.name

def save(self, *args, **kwargs):
def save(self, *args, update_fields: Optional[Iterable[str]] = None, **kwargs):
"""create a link"""
# get or create the associated domain
if not self.domain:
domain = urlparse(self.url).hostname
self.domain, _ = LinkDomain.objects.get_or_create(domain=domain)
update_fields = add_update_fields(update_fields, "domain")

# this is never broadcast, the owning model broadcasts an update
if "broadcast" in kwargs:
del kwargs["broadcast"]
return super().save(*args, **kwargs)

super().save(*args, update_fields=update_fields, **kwargs)


AvailabilityChoices = [
Expand Down Expand Up @@ -88,8 +92,10 @@ def raise_not_editable(self, viewer):
return
raise PermissionDenied()

def save(self, *args, **kwargs):
def save(self, *args, update_fields: Optional[Iterable[str]] = None, **kwargs):
"""set a default name"""
if not self.name:
self.name = self.domain
super().save(*args, **kwargs)
update_fields = add_update_fields(update_fields, "name")

super().save(*args, update_fields=update_fields, **kwargs)
8 changes: 6 additions & 2 deletions bookwyrm/models/list.py
@@ -1,4 +1,5 @@
""" make a list of books!! """
from typing import Optional, Iterable
import uuid

from django.core.exceptions import PermissionDenied
Expand All @@ -8,6 +9,7 @@

from bookwyrm import activitypub
from bookwyrm.settings import BASE_URL
from bookwyrm.utils.db import add_update_fields

from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
from .base_model import BookWyrmModel
Expand Down Expand Up @@ -124,11 +126,13 @@ def remove_from_group(cls, owner, user):
group=None, curation="closed"
)

def save(self, *args, **kwargs):
def save(self, *args, update_fields: Optional[Iterable[str]] = None, **kwargs):
"""on save, update embed_key and avoid clash with existing code"""
if not self.embed_key:
self.embed_key = uuid.uuid4()
super().save(*args, **kwargs)
update_fields = add_update_fields(update_fields, "embed_key")

super().save(*args, update_fields=update_fields, **kwargs)


class ListItem(CollectionItemMixin, BookWyrmModel):
Expand Down
9 changes: 7 additions & 2 deletions bookwyrm/models/readthrough.py
@@ -1,9 +1,13 @@
""" progress in a book """
from typing import Optional, Iterable

from django.core import validators
from django.core.cache import cache
from django.db import models
from django.db.models import F, Q

from bookwyrm.utils.db import add_update_fields

from .base_model import BookWyrmModel


Expand All @@ -30,13 +34,14 @@ class ReadThrough(BookWyrmModel):
stopped_date = models.DateTimeField(blank=True, null=True)
is_active = models.BooleanField(default=True)

def save(self, *args, **kwargs):
def save(self, *args, update_fields: Optional[Iterable[str]] = None, **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
update_fields = add_update_fields(update_fields, "is_active")

super().save(*args, **kwargs)
super().save(*args, update_fields=update_fields, **kwargs)

cache.delete(f"latest_read_through-{self.user_id}-{self.book_id}")
self.user.update_active_date()
Expand Down
15 changes: 12 additions & 3 deletions bookwyrm/models/shelf.py
@@ -1,5 +1,6 @@
""" puttin' books on shelves """
import re
from typing import Optional, Iterable
from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from django.db import models
Expand All @@ -8,6 +9,7 @@
from bookwyrm import activitypub
from bookwyrm.settings import BASE_URL
from bookwyrm.tasks import BROADCAST
from bookwyrm.utils.db import add_update_fields
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
from .base_model import BookWyrmModel
from . import fields
Expand Down Expand Up @@ -46,7 +48,7 @@ def save(self, *args, priority=BROADCAST, **kwargs):
if not self.identifier:
# this needs the auto increment ID from the save() above
self.identifier = self.get_identifier()
super().save(*args, **kwargs, broadcast=False)
super().save(*args, **kwargs, broadcast=False, update_fields={"identifier"})

def get_identifier(self):
"""custom-shelf-123 for the url"""
Expand Down Expand Up @@ -101,12 +103,19 @@ class ShelfBook(CollectionItemMixin, BookWyrmModel):
activity_serializer = activitypub.ShelfItem
collection_field = "shelf"

def save(self, *args, priority=BROADCAST, **kwargs):
def save(
self,
*args,
priority=BROADCAST,
update_fields: Optional[Iterable[str]] = None,
**kwargs,
):
if not self.user:
self.user = self.shelf.user
update_fields = add_update_fields(update_fields, "user")

is_update = self.id is not None
super().save(*args, priority=priority, **kwargs)
super().save(*args, priority=priority, update_fields=update_fields, **kwargs)

if is_update and self.user.local:
# remove all caches related to all editions of this book
Expand Down
7 changes: 5 additions & 2 deletions bookwyrm/models/site.py
@@ -1,5 +1,6 @@
""" the particulars for this instance of BookWyrm """
import datetime
from typing import Optional, Iterable
from urllib.parse import urljoin
import uuid

Expand All @@ -15,6 +16,7 @@
from bookwyrm.settings import BASE_URL, ENABLE_PREVIEW_IMAGES, STATIC_FULL_URL
from bookwyrm.settings import RELEASE_API
from bookwyrm.tasks import app, MISC
from bookwyrm.utils.db import add_update_fields
from .base_model import BookWyrmModel, new_access_code
from .user import User
from .fields import get_absolute_url
Expand Down Expand Up @@ -136,13 +138,14 @@ def get_url(self, field, default_path):
return get_absolute_url(uploaded)
return urljoin(STATIC_FULL_URL, default_path)

def save(self, *args, **kwargs):
def save(self, *args, update_fields: Optional[Iterable[str]] = None, **kwargs):
"""if require_confirm_email is disabled, make sure no users are pending,
if enabled, make sure invite_question_text is not empty"""
if not self.invite_question_text:
self.invite_question_text = "What is your favourite book?"
update_fields = add_update_fields(update_fields, "invite_question_text")

super().save(*args, **kwargs)
super().save(*args, update_fields=update_fields, **kwargs)

if not self.require_confirm_email:
User.objects.filter(is_active=False, deactivation_reason="pending").update(
Expand Down
10 changes: 6 additions & 4 deletions bookwyrm/models/status.py
@@ -1,6 +1,6 @@
""" models for storing different kinds of Activities """
from dataclasses import MISSING
from typing import Optional
from typing import Optional, Iterable
import re

from django.apps import apps
Expand All @@ -20,6 +20,7 @@
from bookwyrm import activitypub
from bookwyrm.preview_images import generate_edition_preview_image_task
from bookwyrm.settings import ENABLE_PREVIEW_IMAGES
from bookwyrm.utils.db import add_update_fields
from .activitypub_mixin import ActivitypubMixin, ActivityMixin
from .activitypub_mixin import OrderedCollectionPageMixin
from .base_model import BookWyrmModel
Expand Down Expand Up @@ -85,12 +86,13 @@ class Meta:
models.Index(fields=["thread_id"]),
]

def save(self, *args, **kwargs):
def save(self, *args, update_fields: Optional[Iterable[str]] = None, **kwargs):
"""save and notify"""
if self.reply_parent:
if self.thread_id is None and self.reply_parent:
self.thread_id = self.reply_parent.thread_id or self.reply_parent_id
update_fields = add_update_fields(update_fields, "thread_id")

super().save(*args, **kwargs)
super().save(*args, update_fields=update_fields, **kwargs)

if not self.reply_parent:
self.thread_id = self.id
Expand Down

0 comments on commit e7f95ef

Please sign in to comment.