diff --git a/src/documents/migrations/0011_optimize_integer_field_sizes.py b/src/documents/migrations/0011_optimize_integer_field_sizes.py new file mode 100644 index 000000000..d656fe35e --- /dev/null +++ b/src/documents/migrations/0011_optimize_integer_field_sizes.py @@ -0,0 +1,227 @@ +# Generated by Django 5.2.11 on 2026-02-09 16:37 + +import django.core.validators +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + dependencies = [ + ("documents", "0010_alter_document_content_length"), + ] + + operations = [ + migrations.AlterField( + model_name="correspondent", + name="matching_algorithm", + field=models.PositiveSmallIntegerField( + choices=[ + (0, "None"), + (1, "Any word"), + (2, "All words"), + (3, "Exact match"), + (4, "Regular expression"), + (5, "Fuzzy word"), + (6, "Automatic"), + ], + default=1, + verbose_name="matching algorithm", + ), + ), + migrations.AlterField( + model_name="documenttype", + name="matching_algorithm", + field=models.PositiveSmallIntegerField( + choices=[ + (0, "None"), + (1, "Any word"), + (2, "All words"), + (3, "Exact match"), + (4, "Regular expression"), + (5, "Fuzzy word"), + (6, "Automatic"), + ], + default=1, + verbose_name="matching algorithm", + ), + ), + migrations.AlterField( + model_name="savedviewfilterrule", + name="rule_type", + field=models.PositiveSmallIntegerField( + choices=[ + (0, "title contains"), + (1, "content contains"), + (2, "ASN is"), + (3, "correspondent is"), + (4, "document type is"), + (5, "is in inbox"), + (6, "has tag"), + (7, "has any tag"), + (8, "created before"), + (9, "created after"), + (10, "created year is"), + (11, "created month is"), + (12, "created day is"), + (13, "added before"), + (14, "added after"), + (15, "modified before"), + (16, "modified after"), + (17, "does not have tag"), + (18, "does not have ASN"), + (19, "title or content contains"), + (20, "fulltext query"), + (21, "more like this"), + (22, "has tags in"), + (23, "ASN greater than"), + (24, "ASN less than"), + (25, "storage path is"), + (26, "has correspondent in"), + (27, "does not have correspondent in"), + (28, "has document type in"), + (29, "does not have document type in"), + (30, "has storage path in"), + (31, "does not have storage path in"), + (32, "owner is"), + (33, "has owner in"), + (34, "does not have owner"), + (35, "does not have owner in"), + (36, "has custom field value"), + (37, "is shared by me"), + (38, "has custom fields"), + (39, "has custom field in"), + (40, "does not have custom field in"), + (41, "does not have custom field"), + (42, "custom fields query"), + (43, "created to"), + (44, "created from"), + (45, "added to"), + (46, "added from"), + (47, "mime type is"), + ], + verbose_name="rule type", + ), + ), + migrations.AlterField( + model_name="storagepath", + name="matching_algorithm", + field=models.PositiveSmallIntegerField( + choices=[ + (0, "None"), + (1, "Any word"), + (2, "All words"), + (3, "Exact match"), + (4, "Regular expression"), + (5, "Fuzzy word"), + (6, "Automatic"), + ], + default=1, + verbose_name="matching algorithm", + ), + ), + migrations.AlterField( + model_name="tag", + name="matching_algorithm", + field=models.PositiveSmallIntegerField( + choices=[ + (0, "None"), + (1, "Any word"), + (2, "All words"), + (3, "Exact match"), + (4, "Regular expression"), + (5, "Fuzzy word"), + (6, "Automatic"), + ], + default=1, + verbose_name="matching algorithm", + ), + ), + migrations.AlterField( + model_name="workflow", + name="order", + field=models.SmallIntegerField(default=0, verbose_name="order"), + ), + migrations.AlterField( + model_name="workflowaction", + name="order", + field=models.PositiveSmallIntegerField(default=0, verbose_name="order"), + ), + migrations.AlterField( + model_name="workflowaction", + name="type", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Assignment"), + (2, "Removal"), + (3, "Email"), + (4, "Webhook"), + (5, "Password removal"), + ], + default=1, + verbose_name="Workflow Action Type", + ), + ), + migrations.AlterField( + model_name="workflowrun", + name="type", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Consumption Started"), + (2, "Document Added"), + (3, "Document Updated"), + (4, "Scheduled"), + ], + null=True, + verbose_name="workflow trigger type", + ), + ), + migrations.AlterField( + model_name="workflowtrigger", + name="matching_algorithm", + field=models.PositiveSmallIntegerField( + choices=[ + (0, "None"), + (1, "Any word"), + (2, "All words"), + (3, "Exact match"), + (4, "Regular expression"), + (5, "Fuzzy word"), + ], + default=0, + verbose_name="matching algorithm", + ), + ), + migrations.AlterField( + model_name="workflowtrigger", + name="schedule_offset_days", + field=models.SmallIntegerField( + default=0, + help_text="The number of days to offset the schedule trigger by.", + verbose_name="schedule offset days", + ), + ), + migrations.AlterField( + model_name="workflowtrigger", + name="schedule_recurring_interval_days", + field=models.PositiveSmallIntegerField( + default=1, + help_text="The number of days between recurring schedule triggers.", + validators=[django.core.validators.MinValueValidator(1)], + verbose_name="schedule recurring delay in days", + ), + ), + migrations.AlterField( + model_name="workflowtrigger", + name="type", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Consumption Started"), + (2, "Document Added"), + (3, "Document Updated"), + (4, "Scheduled"), + ], + default=1, + verbose_name="Workflow Trigger Type", + ), + ), + ] diff --git a/src/documents/models.py b/src/documents/models.py index 5a813f9b5..7700eba19 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -67,7 +67,7 @@ class MatchingModel(ModelWithOwner): match = models.CharField(_("match"), max_length=256, blank=True) - matching_algorithm = models.PositiveIntegerField( + matching_algorithm = models.PositiveSmallIntegerField( _("matching algorithm"), choices=MATCHING_ALGORITHMS, default=MATCH_ANY, @@ -547,7 +547,7 @@ class SavedViewFilterRule(models.Model): verbose_name=_("saved view"), ) - rule_type = models.PositiveIntegerField(_("rule type"), choices=RULE_TYPES) + rule_type = models.PositiveSmallIntegerField(_("rule type"), choices=RULE_TYPES) value = models.CharField(_("value"), max_length=255, blank=True, null=True) @@ -1102,7 +1102,7 @@ class WorkflowTrigger(models.Model): MODIFIED = "modified", _("Modified") CUSTOM_FIELD = "custom_field", _("Custom Field") - type = models.PositiveIntegerField( + type = models.PositiveSmallIntegerField( _("Workflow Trigger Type"), choices=WorkflowTriggerType.choices, default=WorkflowTriggerType.CONSUMPTION, @@ -1148,7 +1148,7 @@ class WorkflowTrigger(models.Model): match = models.CharField(_("match"), max_length=256, blank=True) - matching_algorithm = models.PositiveIntegerField( + matching_algorithm = models.PositiveSmallIntegerField( _("matching algorithm"), choices=WorkflowTriggerMatching.choices, default=WorkflowTriggerMatching.NONE, @@ -1249,7 +1249,7 @@ class WorkflowTrigger(models.Model): help_text=_("JSON-encoded custom field query expression."), ) - schedule_offset_days = models.IntegerField( + schedule_offset_days = models.SmallIntegerField( _("schedule offset days"), default=0, help_text=_( @@ -1265,7 +1265,7 @@ class WorkflowTrigger(models.Model): ), ) - schedule_recurring_interval_days = models.PositiveIntegerField( + schedule_recurring_interval_days = models.PositiveSmallIntegerField( _("schedule recurring delay in days"), default=1, validators=[MinValueValidator(1)], @@ -1410,13 +1410,13 @@ class WorkflowAction(models.Model): _("Password removal"), ) - type = models.PositiveIntegerField( + type = models.PositiveSmallIntegerField( _("Workflow Action Type"), choices=WorkflowActionType.choices, default=WorkflowActionType.ASSIGNMENT, ) - order = models.PositiveIntegerField(_("order"), default=0) + order = models.PositiveSmallIntegerField(_("order"), default=0) assign_title = models.TextField( _("assign title"), @@ -1658,7 +1658,7 @@ class WorkflowAction(models.Model): class Workflow(models.Model): name = models.CharField(_("name"), max_length=256, unique=True) - order = models.IntegerField(_("order"), default=0) + order = models.SmallIntegerField(_("order"), default=0) triggers = models.ManyToManyField( WorkflowTrigger, @@ -1688,7 +1688,7 @@ class WorkflowRun(SoftDeleteModel): verbose_name=_("workflow"), ) - type = models.PositiveIntegerField( + type = models.PositiveSmallIntegerField( _("workflow trigger type"), choices=WorkflowTrigger.WorkflowTriggerType.choices, null=True, diff --git a/src/paperless/migrations/0007_optimize_integer_field_sizes.py b/src/paperless/migrations/0007_optimize_integer_field_sizes.py new file mode 100644 index 000000000..104fc1db0 --- /dev/null +++ b/src/paperless/migrations/0007_optimize_integer_field_sizes.py @@ -0,0 +1,50 @@ +# Generated by Django 5.2.11 on 2026-02-09 16:37 + +import django.core.validators +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + dependencies = [ + ("paperless", "0006_applicationconfiguration_barcode_tag_split"), + ] + + operations = [ + migrations.AlterField( + model_name="applicationconfiguration", + name="barcode_dpi", + field=models.PositiveSmallIntegerField( + null=True, + validators=[django.core.validators.MinValueValidator(1)], + verbose_name="Sets the barcode DPI", + ), + ), + migrations.AlterField( + model_name="applicationconfiguration", + name="barcode_max_pages", + field=models.PositiveSmallIntegerField( + null=True, + validators=[django.core.validators.MinValueValidator(1)], + verbose_name="Sets the maximum pages for barcode", + ), + ), + migrations.AlterField( + model_name="applicationconfiguration", + name="image_dpi", + field=models.PositiveSmallIntegerField( + null=True, + validators=[django.core.validators.MinValueValidator(1)], + verbose_name="Sets image DPI fallback value", + ), + ), + migrations.AlterField( + model_name="applicationconfiguration", + name="pages", + field=models.PositiveSmallIntegerField( + null=True, + validators=[django.core.validators.MinValueValidator(1)], + verbose_name="Do OCR from page 1 to this value", + ), + ), + ] diff --git a/src/paperless/models.py b/src/paperless/models.py index 725bff683..c67f16b03 100644 --- a/src/paperless/models.py +++ b/src/paperless/models.py @@ -105,7 +105,7 @@ class ApplicationConfiguration(AbstractSingletonModel): Settings for the Tesseract based OCR parser """ - pages = models.PositiveIntegerField( + pages = models.PositiveSmallIntegerField( verbose_name=_("Do OCR from page 1 to this value"), null=True, validators=[MinValueValidator(1)], @@ -134,7 +134,7 @@ class ApplicationConfiguration(AbstractSingletonModel): choices=ArchiveFileChoices.choices, ) - image_dpi = models.PositiveIntegerField( + image_dpi = models.PositiveSmallIntegerField( verbose_name=_("Sets image DPI fallback value"), null=True, validators=[MinValueValidator(1)], @@ -254,14 +254,14 @@ class ApplicationConfiguration(AbstractSingletonModel): ) # PAPERLESS_CONSUMER_BARCODE_DPI - barcode_dpi = models.PositiveIntegerField( + barcode_dpi = models.PositiveSmallIntegerField( verbose_name=_("Sets the barcode DPI"), null=True, validators=[MinValueValidator(1)], ) # PAPERLESS_CONSUMER_BARCODE_MAX_PAGES - barcode_max_pages = models.PositiveIntegerField( + barcode_max_pages = models.PositiveSmallIntegerField( verbose_name=_("Sets the maximum pages for barcode"), null=True, validators=[MinValueValidator(1)], diff --git a/src/paperless_mail/migrations/0002_optimize_integer_field_sizes.py b/src/paperless_mail/migrations/0002_optimize_integer_field_sizes.py new file mode 100644 index 000000000..1b82d021c --- /dev/null +++ b/src/paperless_mail/migrations/0002_optimize_integer_field_sizes.py @@ -0,0 +1,144 @@ +# Generated by Django 5.2.11 on 2026-02-09 16:37 + +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + dependencies = [ + ("paperless_mail", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="mailaccount", + name="account_type", + field=models.PositiveSmallIntegerField( + choices=[(1, "IMAP"), (2, "Gmail OAuth"), (3, "Outlook OAuth")], + default=1, + verbose_name="account type", + ), + ), + migrations.AlterField( + model_name="mailaccount", + name="imap_port", + field=models.PositiveIntegerField( + blank=True, + help_text="This is usually 143 for unencrypted and STARTTLS connections, and 993 for SSL connections.", + null=True, + verbose_name="IMAP port", + ), + ), + migrations.AlterField( + model_name="mailaccount", + name="imap_security", + field=models.PositiveSmallIntegerField( + choices=[(1, "No encryption"), (2, "Use SSL"), (3, "Use STARTTLS")], + default=2, + verbose_name="IMAP security", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="action", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Delete"), + (2, "Move to specified folder"), + (3, "Mark as read, don't process read mails"), + (4, "Flag the mail, don't process flagged mails"), + (5, "Tag the mail with specified tag, don't process tagged mails"), + ], + default=3, + verbose_name="action", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="assign_correspondent_from", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Do not assign a correspondent"), + (2, "Use mail address"), + (3, "Use name (or mail address if not available)"), + (4, "Use correspondent selected below"), + ], + default=1, + verbose_name="assign correspondent from", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="assign_title_from", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Use subject as title"), + (2, "Use attachment filename as title"), + (3, "Do not assign title from rule"), + ], + default=1, + verbose_name="assign title from", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="attachment_type", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Only process attachments."), + (2, "Process all files, including 'inline' attachments."), + ], + default=1, + help_text="Inline attachments include embedded images, so it's best to combine this option with a filename filter.", + verbose_name="attachment type", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="consumption_scope", + field=models.PositiveSmallIntegerField( + choices=[ + (1, "Only process attachments."), + ( + 2, + "Process full Mail (with embedded attachments in file) as .eml", + ), + ( + 3, + "Process full Mail (with embedded attachments in file) as .eml + process attachments as separate documents", + ), + ], + default=1, + verbose_name="consumption scope", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="maximum_age", + field=models.PositiveSmallIntegerField( + default=30, + help_text="Specified in days.", + verbose_name="maximum age", + ), + ), + migrations.AlterField( + model_name="mailrule", + name="order", + field=models.SmallIntegerField(default=0, verbose_name="order"), + ), + migrations.AlterField( + model_name="mailrule", + name="pdf_layout", + field=models.PositiveSmallIntegerField( + choices=[ + (0, "System default"), + (1, "Text, then HTML"), + (2, "HTML, then text"), + (3, "HTML only"), + (4, "Text only"), + ], + default=0, + verbose_name="pdf layout", + ), + ), + ] diff --git a/src/paperless_mail/models.py b/src/paperless_mail/models.py index cf33a056b..08906e00c 100644 --- a/src/paperless_mail/models.py +++ b/src/paperless_mail/models.py @@ -24,7 +24,7 @@ class MailAccount(document_models.ModelWithOwner): imap_server = models.CharField(_("IMAP server"), max_length=256) - imap_port = models.IntegerField( + imap_port = models.PositiveIntegerField( _("IMAP port"), blank=True, null=True, @@ -34,7 +34,7 @@ class MailAccount(document_models.ModelWithOwner): ), ) - imap_security = models.PositiveIntegerField( + imap_security = models.PositiveSmallIntegerField( _("IMAP security"), choices=ImapSecurity.choices, default=ImapSecurity.SSL, @@ -56,7 +56,7 @@ class MailAccount(document_models.ModelWithOwner): ), ) - account_type = models.PositiveIntegerField( + account_type = models.PositiveSmallIntegerField( _("account type"), choices=MailAccountType.choices, default=MailAccountType.IMAP, @@ -142,7 +142,7 @@ class MailRule(document_models.ModelWithOwner): name = models.CharField(_("name"), max_length=256) - order = models.IntegerField(_("order"), default=0) + order = models.SmallIntegerField(_("order"), default=0) account = models.ForeignKey( MailAccount, @@ -215,13 +215,13 @@ class MailRule(document_models.ModelWithOwner): ), ) - maximum_age = models.PositiveIntegerField( + maximum_age = models.PositiveSmallIntegerField( _("maximum age"), default=30, help_text=_("Specified in days."), ) - attachment_type = models.PositiveIntegerField( + attachment_type = models.PositiveSmallIntegerField( _("attachment type"), choices=AttachmentProcessing.choices, default=AttachmentProcessing.ATTACHMENTS_ONLY, @@ -231,19 +231,19 @@ class MailRule(document_models.ModelWithOwner): ), ) - consumption_scope = models.PositiveIntegerField( + consumption_scope = models.PositiveSmallIntegerField( _("consumption scope"), choices=ConsumptionScope.choices, default=ConsumptionScope.ATTACHMENTS_ONLY, ) - pdf_layout = models.PositiveIntegerField( + pdf_layout = models.PositiveSmallIntegerField( _("pdf layout"), choices=PdfLayout.choices, default=PdfLayout.DEFAULT, ) - action = models.PositiveIntegerField( + action = models.PositiveSmallIntegerField( _("action"), choices=MailAction.choices, default=MailAction.MARK_READ, @@ -262,7 +262,7 @@ class MailRule(document_models.ModelWithOwner): ), ) - assign_title_from = models.PositiveIntegerField( + assign_title_from = models.PositiveSmallIntegerField( _("assign title from"), choices=TitleSource.choices, default=TitleSource.FROM_SUBJECT, @@ -282,7 +282,7 @@ class MailRule(document_models.ModelWithOwner): verbose_name=_("assign this document type"), ) - assign_correspondent_from = models.PositiveIntegerField( + assign_correspondent_from = models.PositiveSmallIntegerField( _("assign correspondent from"), choices=CorrespondentSource.choices, default=CorrespondentSource.FROM_NOTHING,