diff --git a/ram/bookshelf/admin.py b/ram/bookshelf/admin.py index 6b90ad3..5615472 100644 --- a/ram/bookshelf/admin.py +++ b/ram/bookshelf/admin.py @@ -24,14 +24,48 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin): inlines = (BookImageInline, BookPropertyInline,) list_display = ( "title", + "published", "get_authors", "get_publisher", "publication_year", "number_of_pages" ) + readonly_fields = ("creation_time", "updated_time") search_fields = ("title", "publisher__name", "authors__last_name") list_filter = ("publisher__name", "authors") + fieldsets = ( + ( + None, + { + "fields": ( + "published", + "title", + "authors", + "publisher", + "ISBN", + "language", + "number_of_pages", + "publication_year", + "description", + "purchase_date", + "notes", + "tags", + ) + }, + ), + ( + "Audit", + { + "classes": ("collapse",), + "fields": ( + "creation_time", + "updated_time", + ), + }, + ), + ) + @admin.display(description="Publisher") def get_publisher(self, obj): return obj.publisher.name diff --git a/ram/bookshelf/migrations/0014_book_published.py b/ram/bookshelf/migrations/0014_book_published.py new file mode 100644 index 0000000..5989c2a --- /dev/null +++ b/ram/bookshelf/migrations/0014_book_published.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2024-11-04 13:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookshelf", "0013_book_description"), + ] + + operations = [ + migrations.AddField( + model_name="book", + name="published", + field=models.BooleanField(default=True), + ), + ] diff --git a/ram/bookshelf/models.py b/ram/bookshelf/models.py index f4fa609..73db9be 100644 --- a/ram/bookshelf/models.py +++ b/ram/bookshelf/models.py @@ -1,6 +1,5 @@ import os import shutil -from uuid import uuid4 from django.db import models from django.conf import settings from django.urls import reverse @@ -10,7 +9,7 @@ from tinymce import models as tinymce from metadata.models import Tag from ram.utils import DeduplicatedStorage -from ram.models import Image, PropertyInstance +from ram.models import BaseModel, Image, PropertyInstance class Publisher(models.Model): @@ -39,8 +38,7 @@ class Author(models.Model): return f"{self.last_name} {self.first_name[0]}." -class Book(models.Model): - uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False) +class Book(BaseModel): title = models.CharField(max_length=200) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) @@ -57,9 +55,6 @@ class Book(models.Model): tags = models.ManyToManyField( Tag, related_name="bookshelf", blank=True ) - notes = tinymce.HTMLField(blank=True) - creation_time = models.DateTimeField(auto_now_add=True) - updated_time = models.DateTimeField(auto_now=True) class Meta: ordering = ["title"] diff --git a/ram/bookshelf/urls.py b/ram/bookshelf/urls.py index c9479af..3ccfd11 100644 --- a/ram/bookshelf/urls.py +++ b/ram/bookshelf/urls.py @@ -3,5 +3,5 @@ from bookshelf.views import BookList, BookGet urlpatterns = [ path("book/list", BookList.as_view()), - path("book/get/", BookGet.as_view()), + path("book/get/", BookGet.as_view()), ] diff --git a/ram/bookshelf/views.py b/ram/bookshelf/views.py index 57268b7..166df18 100644 --- a/ram/bookshelf/views.py +++ b/ram/bookshelf/views.py @@ -6,13 +6,16 @@ from bookshelf.serializers import BookSerializer class BookList(ListAPIView): - queryset = Book.objects.all() serializer_class = BookSerializer + def get_queryset(self): + return Book.objects.get_published(self.request.user) + class BookGet(RetrieveAPIView): - queryset = Book.objects.all() serializer_class = BookSerializer lookup_field = "uuid" - schema = AutoSchema(operation_id_base="retrieveBookByUUID") + + def get_queryset(self): + return Book.objects.get_published(self.request.user) diff --git a/ram/consist/admin.py b/ram/consist/admin.py index f489172..53201f8 100644 --- a/ram/consist/admin.py +++ b/ram/consist/admin.py @@ -9,7 +9,7 @@ class ConsistItemInline(SortableInlineAdminMixin, admin.TabularInline): min_num = 1 extra = 0 autocomplete_fields = ("rolling_stock",) - readonly_fields = ("preview", "address", "type", "company", "era") + readonly_fields = ("preview", "published", "address", "type", "company", "era") @admin.register(Consist) @@ -19,7 +19,7 @@ class ConsistAdmin(SortableAdminBase, admin.ModelAdmin): "creation_time", "updated_time", ) - list_display = ("identifier", "company", "era") + list_display = ("identifier", "published", "company", "era") list_filter = list_display search_fields = list_display save_as = True @@ -29,6 +29,7 @@ class ConsistAdmin(SortableAdminBase, admin.ModelAdmin): None, { "fields": ( + "published", "identifier", "consist_address", "company", diff --git a/ram/consist/migrations/0012_consist_published.py b/ram/consist/migrations/0012_consist_published.py new file mode 100644 index 0000000..c8c63f1 --- /dev/null +++ b/ram/consist/migrations/0012_consist_published.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2024-11-04 12:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("consist", "0011_alter_consist_consist_address_alter_consist_era"), + ] + + operations = [ + migrations.AddField( + model_name="consist", + name="published", + field=models.BooleanField(default=True), + ), + ] diff --git a/ram/consist/models.py b/ram/consist/models.py index 5a41fa5..4cc12cc 100644 --- a/ram/consist/models.py +++ b/ram/consist/models.py @@ -1,18 +1,17 @@ import os -from uuid import uuid4 from django.db import models from django.urls import reverse +from django.dispatch import receiver +from django.core.exceptions import ValidationError -from tinymce import models as tinymce - +from ram.models import BaseModel from ram.utils import DeduplicatedStorage from metadata.models import Company, Tag from roster.models import RollingStock -class Consist(models.Model): - uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False) +class Consist(BaseModel): identifier = models.CharField(max_length=128, unique=False) tags = models.ManyToManyField(Tag, related_name="consist", blank=True) consist_address = models.SmallIntegerField( @@ -33,9 +32,6 @@ class Consist(models.Model): null=True, blank=True, ) - notes = tinymce.HTMLField(blank=True) - creation_time = models.DateTimeField(auto_now_add=True) - updated_time = models.DateTimeField(auto_now=True) def __str__(self): return "{0} {1}".format(self.company, self.identifier) @@ -43,6 +39,12 @@ class Consist(models.Model): def get_absolute_url(self): return reverse("consist", kwargs={"uuid": self.uuid}) + def clean(self): + if self.consist_item.filter(rolling_stock__published=False).exists(): + raise ValidationError( + "You must publish all items in the consist before publishing the consist." # noqa: E501 + ) + class Meta: ordering = ["company", "-creation_time"] @@ -60,6 +62,10 @@ class ConsistItem(models.Model): def __str__(self): return "{0}".format(self.rolling_stock) + def published(self): + return self.rolling_stock.published + published.boolean = True + def preview(self): return self.rolling_stock.image.first().image_thumbnail(100) @@ -74,3 +80,14 @@ class ConsistItem(models.Model): def era(self): return self.rolling_stock.era + + +# Unpublish any consist that contains an unpublished rolling stock +# this signal is called after a rolling stock is saved +# it is hosted here to avoid circular imports +@receiver(models.signals.post_save, sender=RollingStock) +def post_save_unpublish_consist(sender, instance, *args, **kwargs): + consists = Consist.objects.filter(consist_item__rolling_stock=instance) + for consist in consists: + consist.published = False + consist.save() diff --git a/ram/consist/views.py b/ram/consist/views.py index b3bb0c0..86cb4b7 100644 --- a/ram/consist/views.py +++ b/ram/consist/views.py @@ -5,11 +5,15 @@ from consist.serializers import ConsistSerializer class ConsistList(ListAPIView): - queryset = Consist.objects.all() serializer_class = ConsistSerializer + def get_queryset(self): + return Consist.objects.get_published(self.request.user) + class ConsistGet(RetrieveAPIView): - queryset = Consist.objects.all() serializer_class = ConsistSerializer lookup_field = "uuid" + + def get_queryset(self): + return Consist.objects.get_published(self.request.user) diff --git a/ram/metadata/models.py b/ram/metadata/models.py index 24fad27..982927c 100644 --- a/ram/metadata/models.py +++ b/ram/metadata/models.py @@ -7,6 +7,7 @@ from django_countries.fields import CountryField from ram.models import Document from ram.utils import DeduplicatedStorage, get_image_preview, slugify +from ram.managers import PublicManager class Property(models.Model): @@ -23,6 +24,8 @@ class Property(models.Model): def __str__(self): return self.name + objects = PublicManager() + class Manufacturer(models.Model): name = models.CharField(max_length=128, unique=True) diff --git a/ram/portal/models.py b/ram/portal/models.py index 52c2014..5238d1b 100644 --- a/ram/portal/models.py +++ b/ram/portal/models.py @@ -9,6 +9,7 @@ from solo.models import SingletonModel from tinymce import models as tinymce from ram import __version__ as app_version +from ram.managers import PublicManager from ram.utils import slugify @@ -72,6 +73,8 @@ class Flatpage(models.Model): ) ) + objects = PublicManager() + @receiver(models.signals.pre_save, sender=Flatpage) def tag_pre_save(sender, instance, **kwargs): diff --git a/ram/portal/templates/base.html b/ram/portal/templates/base.html index 902db02..9d64635 100644 --- a/ram/portal/templates/base.html +++ b/ram/portal/templates/base.html @@ -186,7 +186,7 @@ {% show_bookshelf_menu %} - {% show_flatpages_menu %} + {% show_flatpages_menu user %} {% include 'includes/search.html' %} diff --git a/ram/portal/templatetags/show_menu.py b/ram/portal/templatetags/show_menu.py index c3748ed..44cf520 100644 --- a/ram/portal/templatetags/show_menu.py +++ b/ram/portal/templatetags/show_menu.py @@ -11,6 +11,6 @@ def show_bookshelf_menu(): @register.inclusion_tag('flatpages/flatpages_menu.html') -def show_flatpages_menu(): - menu = Flatpage.objects.filter(published=True).order_by("name") +def show_flatpages_menu(user): + menu = Flatpage.objects.get_published(user).order_by("name") return {"flatpages_menu": menu} diff --git a/ram/portal/views.py b/ram/portal/views.py index 9cba164..6ac607f 100644 --- a/ram/portal/views.py +++ b/ram/portal/views.py @@ -17,7 +17,11 @@ from roster.models import RollingStock from consist.models import Consist from bookshelf.models import Book from metadata.models import ( - Company, Manufacturer, Scale, DecoderDocument, RollingStockType, Tag + Company, + Manufacturer, + Scale, + RollingStockType, + Tag, ) @@ -52,11 +56,7 @@ def get_order_by_field(): class Render404(View): def get(self, request, exception): - return render( - request, - "base.html", - {"title": "404 page not found"} - ) + return render(request, "base.html", {"title": "404 page not found"}) class GetData(View): @@ -65,18 +65,17 @@ class GetData(View): item_type = "rolling_stock" filter = Q() # empty filter by default - def get_data(self): - return RollingStock.objects.order_by( - *get_order_by_field() - ).filter(self.filter) + def get_data(self, request): + return ( + RollingStock.objects.get_published(request.user) + .order_by(*get_order_by_field()) + .filter(self.filter) + ) def get(self, request, page=1): data = [] - for item in self.get_data(): - data.append({ - "type": self.item_type, - "item": item - }) + for item in self.get_data(request): + data.append({"type": self.item_type, "item": item}) paginator = Paginator(data, get_items_per_page()) data = paginator.get_page(page) @@ -101,8 +100,10 @@ class GetRoster(GetData): title = "Roster" item_type = "rolling_stock" - def get_data(self): - return RollingStock.objects.order_by(*get_order_by_field()) + def get_data(self, request): + return RollingStock.objects.get_published(request.user).order_by( + *get_order_by_field() + ) class SearchObjects(View): @@ -149,18 +150,17 @@ class SearchObjects(View): # FIXME duplicated code! data = [] rolling_stock = ( - RollingStock.objects.filter(query) + RollingStock.objects.get_published(request.user) + .filter(query) .distinct() .order_by(*get_order_by_field()) ) for item in rolling_stock: - data.append({ - "type": "rolling_stock", - "item": item - }) + data.append({"type": "rolling_stock", "item": item}) if _filter is None: consists = ( - Consist.objects.filter( + Consist.objects.get_published(request.user) + .filter( Q( Q(identifier__icontains=search) | Q(company__name__icontains=search) @@ -169,19 +169,14 @@ class SearchObjects(View): .distinct() ) for item in consists: - data.append({ - "type": "consist", - "item": item - }) + data.append({"type": "consist", "item": item}) books = ( - Book.objects.filter(title__icontains=search) + Book.objects.get_published(request.user) + .filter(title__icontains=search) .distinct() ) for item in books: - data.append({ - "type": "book", - "item": item - }) + data.append({"type": "book", "item": item}) paginator = Paginator(data, get_items_per_page()) data = paginator.get_page(page) @@ -211,8 +206,7 @@ class SearchObjects(View): encoded_search = search search = base64.b64decode(search.encode()).decode() except Exception: - encoded_search = base64.b64encode( - search.encode()).decode() + encoded_search = base64.b64encode(search.encode()).decode() _filter, keyword = self.split_search(search) data, matches, page_range = self.run_search( request, keyword, _filter, page @@ -222,7 +216,7 @@ class SearchObjects(View): request, "search.html", { - "title": "Search: \"{}\"".format(search), + "title": 'Search: "{}"'.format(search), "search": search, "encoded_search": encoded_search, "data": data, @@ -239,27 +233,30 @@ class SearchObjects(View): class GetManufacturerItem(View): def get(self, request, manufacturer, search="all", page=1): manufacturer = get_object_or_404( - Manufacturer, - slug__iexact=manufacturer + Manufacturer, slug__iexact=manufacturer ) if search != "all": rolling_stock = get_list_or_404( - RollingStock.objects.order_by(*get_order_by_field()), + RollingStock.objects.get_published(request.user).order_by( + *get_order_by_field() + ), Q( Q(manufacturer=manufacturer) & Q(item_number_slug__exact=search) - ) + ), ) title = "{0}: {1}".format( manufacturer, # all returned records must have the same `item_number``; # just pick it up the first result, otherwise `search` - rolling_stock[0].item_number if rolling_stock else search + rolling_stock[0].item_number if rolling_stock else search, ) else: rolling_stock = ( - RollingStock.objects.order_by(*get_order_by_field()).filter( + RollingStock.objects.get_published(request.user) + .order_by(*get_order_by_field()) + .filter( Q(manufacturer=manufacturer) | Q(rolling_class__manufacturer=manufacturer) ) @@ -268,10 +265,7 @@ class GetManufacturerItem(View): data = [] for item in rolling_stock: - data.append({ - "type": "rolling_stock", - "item": item - }) + data.append({"type": "rolling_stock", "item": item}) paginator = Paginator(data, get_items_per_page()) data = paginator.get_page(page) @@ -315,38 +309,32 @@ class GetObjectsFiltered(View): raise Http404 rolling_stock = ( - RollingStock.objects.filter(query) + RollingStock.objects.get_published(request.user) + .filter(query) .distinct() .order_by(*get_order_by_field()) ) data = [] for item in rolling_stock: - data.append({ - "type": "rolling_stock", - "item": item - }) + data.append({"type": "rolling_stock", "item": item}) try: # Execute only if query_2nd is defined consists = ( - Consist.objects.filter(query_2nd) + Consist.objects.get_published(request.user) + .filter(query_2nd) .distinct() ) for item in consists: - data.append({ - "type": "consist", - "item": item - }) + data.append({"type": "consist", "item": item}) if _filter == "tag": # Books can be filtered only by tag books = ( - Book.objects.filter(query_2nd) + Book.objects.get_published(request.user) + .filter(query_2nd) .distinct() ) for item in books: - data.append({ - "type": "book", - "item": item - }) + data.append({"type": "book", "item": item}) except NameError: pass @@ -367,8 +355,7 @@ class GetObjectsFiltered(View): request, "filter.html", { - "title": "{0}: {1}".format( - _filter.capitalize(), title), + "title": "{0}: {1}".format(_filter.capitalize(), title), "search": search, "filter": _filter, "data": data, @@ -381,50 +368,44 @@ class GetObjectsFiltered(View): class GetRollingStock(View): def get(self, request, uuid): try: - rolling_stock = RollingStock.objects.get(uuid=uuid) + rolling_stock = RollingStock.objects.get_published( + request.user + ).get(uuid=uuid) except ObjectDoesNotExist: raise Http404 # FIXME there's likely a better and more efficient way of doing this # but keeping KISS for now decoder_documents = [] - if request.user.is_authenticated: - class_properties = rolling_stock.rolling_class.property.all() - properties = rolling_stock.property.all() - documents = rolling_stock.document.all() - journal = rolling_stock.journal.all() - if rolling_stock.decoder: - decoder_documents = rolling_stock.decoder.document.all() - else: - class_properties = rolling_stock.rolling_class.property.filter( - property__private=False + class_properties = rolling_stock.rolling_class.property.get_public( + request.user + ) + properties = rolling_stock.property.get_public(request.user) + documents = rolling_stock.document.get_public(request.user) + journal = rolling_stock.journal.get_public(request.user) + if rolling_stock.decoder: + decoder_documents = rolling_stock.decoder.document.get_public( + request.user ) - properties = rolling_stock.property.filter( - property__private=False + + consists = [ + {"type": "consist", "item": c} + for c in Consist.objects.get_published(request.user).filter( + consist_item__rolling_stock=rolling_stock ) - documents = rolling_stock.document.filter(private=False) - journal = rolling_stock.journal.filter(private=False) - if rolling_stock.decoder: - decoder_documents = rolling_stock.decoder.document.filter( - private=False - ) + ] # A dict with "item" is required by the consists card - consists = [{ - "type": "consist", - "item": c - } for c in Consist.objects.filter( - consist_item__rolling_stock=rolling_stock - )] # A dict with "item" is required by the consists card - - set = [{ - "type": "set", - "item": s - } for s in RollingStock.objects.filter( + set = [ + {"type": "set", "item": s} + for s in RollingStock.objects.get_published(request.user) + .filter( Q( Q(item_number__exact=rolling_stock.item_number) & Q(set=True) ) - ).order_by(*get_order_by_field())] + ) + .order_by(*get_order_by_field()) + ] return render( request, @@ -447,20 +428,27 @@ class Consists(GetData): title = "Consists" item_type = "consist" - def get_data(self): - return Consist.objects.all() + def get_data(self, request): + return Consist.objects.get_published(request.user).all() class GetConsist(View): def get(self, request, uuid, page=1): try: - consist = Consist.objects.get(uuid=uuid) + consist = Consist.objects.get_published(request.user).get( + uuid=uuid + ) except ObjectDoesNotExist: raise Http404 - data = [{ - "type": "rolling_stock", - "item": RollingStock.objects.get(uuid=r.rolling_stock_id) - } for r in consist.consist_item.all()] + data = [ + { + "type": "rolling_stock", + "item": RollingStock.objects.get_published(request.user).get( + uuid=r.rolling_stock_id + ), + } + for r in consist.consist_item.all() + ] paginator = Paginator(data, get_items_per_page()) data = paginator.get_page(page) @@ -525,22 +513,18 @@ class Books(GetData): title = "Books" item_type = "book" - def get_data(self): - return Book.objects.all() + def get_data(self, request): + return Book.objects.get_published(request.user).all() class GetBook(View): def get(self, request, uuid): try: - book = Book.objects.get(uuid=uuid) + book = Book.objects.get_published(request.user).get(uuid=uuid) except ObjectDoesNotExist: raise Http404 - book_properties = ( - book.property.all() - if request.user.is_authenticated - else book.property.filter(property__private=False) - ) + book_properties = book.property.get_public(request.user) return render( request, "bookshelf/book.html", @@ -554,12 +538,10 @@ class GetBook(View): class GetFlatpage(View): def get(self, request, flatpage): - _filter = Q(published=True) # Show only published pages - if request.user.is_authenticated: - _filter = Q() # Reset the filter if user is authenticated - try: - flatpage = Flatpage.objects.filter(_filter).get(path=flatpage) + flatpage = Flatpage.objects.get_published(request.user).get( + path=flatpage + ) except ObjectDoesNotExist: raise Http404 diff --git a/ram/ram/__init__.py b/ram/ram/__init__.py index 828387f..2ea3cfe 100644 --- a/ram/ram/__init__.py +++ b/ram/ram/__init__.py @@ -1,4 +1,4 @@ from ram.utils import git_suffix -__version__ = "0.13.0" +__version__ = "0.13.1" __version__ += git_suffix(__file__) diff --git a/ram/ram/managers.py b/ram/ram/managers.py new file mode 100644 index 0000000..628e413 --- /dev/null +++ b/ram/ram/managers.py @@ -0,0 +1,19 @@ +from django.db import models +from django.core.exceptions import FieldError + + +class PublicManager(models.Manager): + def get_published(self, user): + if user.is_authenticated: + return self.get_queryset() + else: + return self.get_queryset().filter(published=True) + + def get_public(self, user): + if user.is_authenticated: + return self.get_queryset() + else: + try: + return self.get_queryset().filter(private=False) + except FieldError: + return self.get_queryset().filter(property__private=False) diff --git a/ram/ram/models.py b/ram/ram/models.py index 3be5672..3a02b2c 100644 --- a/ram/ram/models.py +++ b/ram/ram/models.py @@ -1,9 +1,25 @@ import os +from uuid import uuid4 from django.db import models from django.utils.safestring import mark_safe +from tinymce import models as tinymce from ram.utils import DeduplicatedStorage, get_image_preview +from ram.managers import PublicManager + + +class BaseModel(models.Model): + uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False) + notes = tinymce.HTMLField(blank=True) + creation_time = models.DateTimeField(auto_now_add=True) + updated_time = models.DateTimeField(auto_now=True) + published = models.BooleanField(default=True) + + class Meta: + abstract = True + + objects = PublicManager() class Document(models.Model): @@ -28,6 +44,8 @@ class Document(models.Model): 'Link'.format(self.file.url) ) + objects = PublicManager() + class Image(models.Model): order = models.PositiveIntegerField(default=0, blank=False, null=False) @@ -48,6 +66,8 @@ class Image(models.Model): abstract = True ordering = ["order"] + objects = PublicManager() + class PropertyInstance(models.Model): property = models.ForeignKey( @@ -62,3 +82,5 @@ class PropertyInstance(models.Model): class Meta: abstract = True verbose_name_plural = "Properties" + + objects = PublicManager() diff --git a/ram/roster/admin.py b/ram/roster/admin.py index 7206e49..e047c1a 100644 --- a/ram/roster/admin.py +++ b/ram/roster/admin.py @@ -111,6 +111,7 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin): readonly_fields = ("preview", "creation_time", "updated_time") list_display = ( "__str__", + "published", "address", "manufacturer", "scale", @@ -141,6 +142,7 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin): { "fields": ( "preview", + "published", "rolling_class", "road_number", "scale", diff --git a/ram/roster/migrations/0028_rollingstock_published.py b/ram/roster/migrations/0028_rollingstock_published.py new file mode 100644 index 0000000..e123246 --- /dev/null +++ b/ram/roster/migrations/0028_rollingstock_published.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2024-11-04 12:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("roster", "0027_alter_rollingstock_decoder_interface"), + ] + + operations = [ + migrations.AddField( + model_name="rollingstock", + name="published", + field=models.BooleanField(default=True), + ), + ] diff --git a/ram/roster/models.py b/ram/roster/models.py index 0464979..96e2fab 100644 --- a/ram/roster/models.py +++ b/ram/roster/models.py @@ -1,7 +1,6 @@ import os import re import shutil -from uuid import uuid4 from django.db import models from django.urls import reverse from django.conf import settings @@ -9,8 +8,9 @@ from django.dispatch import receiver from tinymce import models as tinymce -from ram.models import Document, Image, PropertyInstance +from ram.models import BaseModel, Document, Image, PropertyInstance from ram.utils import DeduplicatedStorage +from ram.managers import PublicManager from metadata.models import ( Scale, Manufacturer, @@ -54,8 +54,7 @@ class RollingClassProperty(PropertyInstance): ) -class RollingStock(models.Model): - uuid = models.UUIDField(primary_key=True, default=uuid4, editable=False) +class RollingStock(BaseModel): rolling_class = models.ForeignKey( RollingClass, on_delete=models.CASCADE, @@ -106,9 +105,6 @@ class RollingStock(models.Model): tags = models.ManyToManyField( Tag, related_name="rolling_stock", blank=True ) - notes = tinymce.HTMLField(blank=True) - creation_time = models.DateTimeField(auto_now_add=True) - updated_time = models.DateTimeField(auto_now=True) class Meta: ordering = ["rolling_class", "road_number_int"] @@ -210,6 +206,8 @@ class RollingStockJournal(models.Model): class Meta: ordering = ["date", "rolling_stock"] + objects = PublicManager() + # @receiver(models.signals.post_delete, sender=Cab) # def post_save_image(sender, instance, *args, **kwargs): diff --git a/ram/roster/urls.py b/ram/roster/urls.py index 1779f5b..d10ac91 100644 --- a/ram/roster/urls.py +++ b/ram/roster/urls.py @@ -3,7 +3,7 @@ from roster.views import RosterList, RosterGet, RosterAddress, RosterClass urlpatterns = [ path("list", RosterList.as_view()), - path("get/", RosterGet.as_view()), + path("get/", RosterGet.as_view()), path("address/", RosterAddress.as_view()), path("class/", RosterClass.as_view()), ] diff --git a/ram/roster/views.py b/ram/roster/views.py index 79a306c..67fe369 100644 --- a/ram/roster/views.py +++ b/ram/roster/views.py @@ -6,26 +6,30 @@ from roster.serializers import RollingStockSerializer class RosterList(ListAPIView): - queryset = RollingStock.objects.all() serializer_class = RollingStockSerializer + def get_queryset(self): + return RollingStock.objects.get_published(self.request.user) + class RosterGet(RetrieveAPIView): - queryset = RollingStock.objects.all() serializer_class = RollingStockSerializer lookup_field = "uuid" - schema = AutoSchema(operation_id_base="retrieveRollingStockByUUID") + def get_queryset(self): + return RollingStock.objects.get_published(self.request.user) + class RosterAddress(ListAPIView): serializer_class = RollingStockSerializer - schema = AutoSchema(operation_id_base="retrieveRollingStockByAddress") def get_queryset(self): address = self.kwargs["address"] - return RollingStock.objects.filter(address=address) + return RollingStock.objects.get_published(self.request.user).filter( + address=address + ) class RosterClass(ListAPIView): @@ -35,4 +39,6 @@ class RosterClass(ListAPIView): def get_queryset(self): _class = self.kwargs["class"] - return RollingStock.objects.filter(rolling_class__identifier=_class) + return RollingStock.objects.get_published(self.request.user).filter( + rolling_class__identifier=_class + )