88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """ puttin' books on shelves """
 | |
| import re
 | |
| from django.db import models
 | |
| 
 | |
| from bookwyrm import activitypub
 | |
| from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
 | |
| from .base_model import BookWyrmModel
 | |
| from . import fields
 | |
| 
 | |
| 
 | |
| class Shelf(OrderedCollectionMixin, BookWyrmModel):
 | |
|     """ a list of books owned by a user """
 | |
| 
 | |
|     TO_READ = "to-read"
 | |
|     READING = "reading"
 | |
|     READ_FINISHED = "read"
 | |
| 
 | |
|     READ_STATUS_IDENTIFIERS = (TO_READ, READING, READ_FINISHED)
 | |
| 
 | |
|     name = fields.CharField(max_length=100)
 | |
|     identifier = models.CharField(max_length=100)
 | |
|     user = fields.ForeignKey(
 | |
|         "User", on_delete=models.PROTECT, activitypub_field="owner"
 | |
|     )
 | |
|     editable = models.BooleanField(default=True)
 | |
|     privacy = fields.PrivacyField()
 | |
|     books = models.ManyToManyField(
 | |
|         "Edition",
 | |
|         symmetrical=False,
 | |
|         through="ShelfBook",
 | |
|         through_fields=("shelf", "book"),
 | |
|     )
 | |
| 
 | |
|     activity_serializer = activitypub.Shelf
 | |
| 
 | |
|     def save(self, *args, **kwargs):
 | |
|         """ set the identifier """
 | |
|         super().save(*args, **kwargs)
 | |
|         if not self.identifier:
 | |
|             slug = re.sub(r"[^\w]", "", self.name).lower()
 | |
|             self.identifier = "%s-%d" % (slug, self.id)
 | |
|             super().save(*args, **kwargs)
 | |
| 
 | |
|     @property
 | |
|     def collection_queryset(self):
 | |
|         """ list of books for this shelf, overrides OrderedCollectionMixin  """
 | |
|         return self.books.all().order_by("shelfbook")
 | |
| 
 | |
|     def get_remote_id(self):
 | |
|         """ shelf identifier instead of id """
 | |
|         base_path = self.user.remote_id
 | |
|         return "%s/books/%s" % (base_path, self.identifier)
 | |
| 
 | |
|     class Meta:
 | |
|         """ user/shelf unqiueness """
 | |
| 
 | |
|         unique_together = ("user", "identifier")
 | |
| 
 | |
| 
 | |
| class ShelfBook(CollectionItemMixin, BookWyrmModel):
 | |
|     """ many to many join table for books and shelves """
 | |
| 
 | |
|     book = fields.ForeignKey(
 | |
|         "Edition", on_delete=models.PROTECT, activitypub_field="object"
 | |
|     )
 | |
|     shelf = fields.ForeignKey(
 | |
|         "Shelf", on_delete=models.PROTECT, activitypub_field="target"
 | |
|     )
 | |
|     user = fields.ForeignKey(
 | |
|         "User", on_delete=models.PROTECT, activitypub_field="actor"
 | |
|     )
 | |
| 
 | |
|     activity_serializer = activitypub.Add
 | |
|     object_field = "book"
 | |
|     collection_field = "shelf"
 | |
| 
 | |
|     def save(self, *args, **kwargs):
 | |
|         if not self.user:
 | |
|             self.user = self.shelf.user
 | |
|         super().save(*args, **kwargs)
 | |
| 
 | |
|     class Meta:
 | |
|         """an opinionated constraint!
 | |
|         you can't put a book on shelf twice"""
 | |
| 
 | |
|         unique_together = ("book", "shelf")
 | |
|         ordering = ("-created_date",)
 |