From d8b254e55e70cb41a9899d9ebc0056b6278b6b87 Mon Sep 17 00:00:00 2001 From: Trenton H <797416+stumpylog@users.noreply.github.com> Date: Thu, 14 Dec 2023 09:57:50 -0800 Subject: [PATCH] Moving the settings to main paperless application --- .../migrations/0001_initial.py | 119 ++++++++++++++---- .../migrations/__init__.py | 0 .../models.py | 82 ++++++++---- src/paperless/serialisers.py | 8 ++ src/paperless/views.py | 11 ++ src/paperless_tesseract/serialisers.py | 9 -- src/paperless_tesseract/views.py | 14 --- 7 files changed, 175 insertions(+), 68 deletions(-) rename src/{paperless_tesseract => paperless}/migrations/0001_initial.py (69%) rename src/{paperless_tesseract => paperless}/migrations/__init__.py (100%) rename src/{paperless_tesseract => paperless}/models.py (76%) delete mode 100644 src/paperless_tesseract/serialisers.py delete mode 100644 src/paperless_tesseract/views.py diff --git a/src/paperless_tesseract/migrations/0001_initial.py b/src/paperless/migrations/0001_initial.py similarity index 69% rename from src/paperless_tesseract/migrations/0001_initial.py rename to src/paperless/migrations/0001_initial.py index b4453aa40..db6617a6e 100644 --- a/src/paperless_tesseract/migrations/0001_initial.py +++ b/src/paperless/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.7 on 2023-12-11 19:59 +# Generated by Django 4.2.7 on 2023-12-14 17:12 import django.core.validators from django.db import migrations @@ -6,8 +6,12 @@ from django.db import models def _create_singleton(apps, schema_editor): - settings_model = apps.get_model("paperless_tesseract", "OcrSettings") - settings_model.objects.create() + """ + Creates the first and only instance of the settings models + """ + for model_name in ["CommonSettings", "OcrSettings", "TextSettings", "TikaSettings"]: + settings_model = apps.get_model("paperless", model_name) + settings_model.objects.create() class Migration(migrations.Migration): @@ -16,6 +20,39 @@ class Migration(migrations.Migration): dependencies = [] operations = [ + migrations.CreateModel( + name="CommonSettings", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "output_type", + models.CharField( + blank=True, + choices=[ + ("pdf", "pdf"), + ("pdfa", "pdfa"), + ("pdfa-1", "pdfa-1"), + ("pdfa-2", "pdfa-2"), + ("pdfa-3", "pdfa-3"), + ], + max_length=8, + null=True, + verbose_name="Sets the output PDF type", + ), + ), + ], + options={ + "abstract": False, + }, + ), migrations.CreateModel( name="OcrSettings", fields=[ @@ -45,22 +82,6 @@ class Migration(migrations.Migration): verbose_name="Do OCR using these languages", ), ), - ( - "output_type", - models.CharField( - blank=True, - choices=[ - ("pdf", "pdf"), - ("pdfa", "pdfa"), - ("pdfa-1", "pdfa-1"), - ("pdfa-2", "pdfa-2"), - ("pdfa-3", "pdfa-3"), - ], - max_length=8, - null=True, - verbose_name="Sets the output PDF type", - ), - ), ( "mode", models.CharField( @@ -135,7 +156,7 @@ class Migration(migrations.Migration): models.FloatField( null=True, validators=[ - django.core.validators.MinValueValidator(1_000_000.0), + django.core.validators.MinValueValidator(1000000.0), ], verbose_name="Sets the maximum image size for decompression", ), @@ -168,8 +189,60 @@ class Migration(migrations.Migration): "verbose_name": "ocr settings", }, ), - migrations.RunPython( - code=_create_singleton, - reverse_code=migrations.RunPython.noop, + migrations.CreateModel( + name="TextSettings", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "thumbnail_font_name", + models.CharField( + blank=True, + max_length=64, + null=True, + verbose_name="Sets the output PDF type", + ), + ), + ], + options={ + "abstract": False, + }, ), + migrations.CreateModel( + name="TikaSettings", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "tika_url", + models.URLField(blank=True, null=True, verbose_name="Tika URL"), + ), + ( + "gotenberg_url", + models.URLField( + blank=True, + null=True, + verbose_name="Gotenberg URL", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.RunPython(_create_singleton, migrations.RunPython.noop), ] diff --git a/src/paperless_tesseract/migrations/__init__.py b/src/paperless/migrations/__init__.py similarity index 100% rename from src/paperless_tesseract/migrations/__init__.py rename to src/paperless/migrations/__init__.py diff --git a/src/paperless_tesseract/models.py b/src/paperless/models.py similarity index 76% rename from src/paperless_tesseract/models.py rename to src/paperless/models.py index 2ced63944..0c0dd65e3 100644 --- a/src/paperless_tesseract/models.py +++ b/src/paperless/models.py @@ -1,4 +1,3 @@ -from django.core.exceptions import ValidationError from django.core.validators import MinValueValidator from django.db import models from django.utils.translation import gettext_lazy as _ @@ -6,7 +5,23 @@ from django.utils.translation import gettext_lazy as _ DEFAULT_SINGLETON_INSTANCE_ID = 1 -class OcrSettings(models.Model): +class AbstractSingletonModel(models.Model): + class Meta: + abstract = True + + def save(self, *args, **kwargs): + """ + Always save as the first and only model + """ + self.pk = DEFAULT_SINGLETON_INSTANCE_ID + super().save(*args, **kwargs) + + +class CommonSettings(AbstractSingletonModel): + """ + Settings which are common across more than 1 parser + """ + class OutputTypeChoices(models.TextChoices): PDF = ("pdf", _("pdf")) PDF_A = ("pdfa", _("pdfa")) @@ -14,6 +29,20 @@ class OcrSettings(models.Model): PDF_A2 = ("pdfa-2", _("pdfa-2")) PDF_A3 = ("pdfa-3", _("pdfa-3")) + output_type = models.CharField( + verbose_name=_("Sets the output PDF type"), + null=True, + blank=True, + max_length=8, + choices=OutputTypeChoices.choices, + ) + + +class OcrSettings(AbstractSingletonModel): + """ + Settings for the Tesseract based OCR parser + """ + class ModeChoices(models.TextChoices): SKIP = ("skip", _("skip")) SKIP_NO_ARCHIVE = ("skip_noarchive", _("skip_noarchive")) @@ -50,14 +79,6 @@ class OcrSettings(models.Model): max_length=32, ) - output_type = models.CharField( - verbose_name=_("Sets the output PDF type"), - null=True, - blank=True, - max_length=8, - choices=OutputTypeChoices.choices, - ) - mode = models.CharField( verbose_name=_("Sets the OCR mode"), null=True, @@ -124,17 +145,34 @@ class OcrSettings(models.Model): verbose_name = _("ocr settings") def __str__(self) -> str: - return "" + return "OcrSettings" - def save(self, *args, **kwargs): - if not self.pk and OcrSettings.objects.exists(): - # if you'll not check for self.pk - # then error will also be raised in the update of exists model - raise ValidationError( - "There is can be only one OcrSettings instance", - ) - return super().save(*args, **kwargs) - @classmethod - def object(cls): - return cls._default_manager.all().first() # Since only one item +class TextSettings(AbstractSingletonModel): + """ + Settings for the text parser + """ + + thumbnail_font_name = models.CharField( + verbose_name=_("Sets the output PDF type"), + null=True, + blank=True, + max_length=64, + ) + + +class TikaSettings(AbstractSingletonModel): + """ + Settings for the Tika parser + """ + + tika_url = models.URLField( + verbose_name=_("Tika URL"), + null=True, + blank=True, + ) + gotenberg_url = models.URLField( + verbose_name=_("Gotenberg URL"), + null=True, + blank=True, + ) diff --git a/src/paperless/serialisers.py b/src/paperless/serialisers.py index 36ba0171e..496a06c5f 100644 --- a/src/paperless/serialisers.py +++ b/src/paperless/serialisers.py @@ -3,6 +3,8 @@ from django.contrib.auth.models import Permission from django.contrib.auth.models import User from rest_framework import serializers +from paperless.models import OcrSettings + class ObfuscatedUserPasswordField(serializers.Field): """ @@ -113,3 +115,9 @@ class ProfileSerializer(serializers.ModelSerializer): "last_name", "auth_token", ) + + +class OcrSettingsSerializer(serializers.ModelSerializer): + class Meta: + model = OcrSettings + fields = ["all"] diff --git a/src/paperless/views.py b/src/paperless/views.py index 084aee3d7..5d04b6bf4 100644 --- a/src/paperless/views.py +++ b/src/paperless/views.py @@ -18,7 +18,9 @@ from rest_framework.viewsets import ModelViewSet from documents.permissions import PaperlessObjectPermissions from paperless.filters import GroupFilterSet from paperless.filters import UserFilterSet +from paperless.models import OcrSettings from paperless.serialisers import GroupSerializer +from paperless.serialisers import OcrSettingsSerializer from paperless.serialisers import ProfileSerializer from paperless.serialisers import UserSerializer @@ -160,3 +162,12 @@ class GenerateAuthTokenView(GenericAPIView): return Response( token.key, ) + + +class OcrSettingsViewSet(ModelViewSet): + model = OcrSettings + + queryset = OcrSettings.objects + + serializer_class = OcrSettingsSerializer + permission_classes = (IsAuthenticated,) diff --git a/src/paperless_tesseract/serialisers.py b/src/paperless_tesseract/serialisers.py deleted file mode 100644 index d25e9eeab..000000000 --- a/src/paperless_tesseract/serialisers.py +++ /dev/null @@ -1,9 +0,0 @@ -from rest_framework import serializers - -from paperless_tesseract.models import OcrSettings - - -class OcrSettingsSerializer(serializers.ModelSerializer): - class Meta: - model = OcrSettings - fields = ["all"] diff --git a/src/paperless_tesseract/views.py b/src/paperless_tesseract/views.py deleted file mode 100644 index 2883a117a..000000000 --- a/src/paperless_tesseract/views.py +++ /dev/null @@ -1,14 +0,0 @@ -from rest_framework.permissions import IsAuthenticated -from rest_framework.viewsets import ModelViewSet - -from paperless_tesseract.models import OcrSettings -from paperless_tesseract.serialisers import OcrSettingsSerializer - - -class OcrSettingsViewSet(ModelViewSet): - model = OcrSettings - - queryset = OcrSettings.objects - - serializer_class = OcrSettingsSerializer - permission_classes = (IsAuthenticated,)