mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-05-03 21:25:23 +00:00
feat: replace versioning migrations with DocumentVersion table, renumber chain
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import django.core.validators
|
||||
import django.db.models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0011_alter_workflowaction_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="DocumentVersion",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"version_number",
|
||||
models.PositiveSmallIntegerField(
|
||||
help_text="Sequential version number within this document, starting at 1.",
|
||||
verbose_name="version number",
|
||||
),
|
||||
),
|
||||
(
|
||||
"version_label",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
help_text="Optional short label for this version.",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="version label",
|
||||
),
|
||||
),
|
||||
(
|
||||
"added",
|
||||
models.DateTimeField(
|
||||
db_index=True,
|
||||
default=django.utils.timezone.now,
|
||||
editable=False,
|
||||
verbose_name="added",
|
||||
),
|
||||
),
|
||||
(
|
||||
"checksum",
|
||||
models.CharField(
|
||||
editable=False,
|
||||
help_text="SHA-256 checksum of the original file for this version.",
|
||||
max_length=64,
|
||||
verbose_name="checksum",
|
||||
),
|
||||
),
|
||||
(
|
||||
"archive_checksum",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
editable=False,
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="archive checksum",
|
||||
),
|
||||
),
|
||||
(
|
||||
"content",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="OCR text content of this version.",
|
||||
verbose_name="content",
|
||||
),
|
||||
),
|
||||
(
|
||||
"page_count",
|
||||
models.PositiveIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[django.core.validators.MinValueValidator(1)],
|
||||
verbose_name="page count",
|
||||
),
|
||||
),
|
||||
(
|
||||
"mime_type",
|
||||
models.CharField(
|
||||
editable=False,
|
||||
max_length=256,
|
||||
verbose_name="mime type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"original_filename",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
editable=False,
|
||||
max_length=1024,
|
||||
null=True,
|
||||
verbose_name="original filename",
|
||||
),
|
||||
),
|
||||
(
|
||||
"filename",
|
||||
models.FilePathField(
|
||||
default=None,
|
||||
editable=False,
|
||||
help_text="Stored filename for this version's original file.",
|
||||
max_length=1024,
|
||||
null=True,
|
||||
verbose_name="filename",
|
||||
),
|
||||
),
|
||||
(
|
||||
"archive_filename",
|
||||
models.FilePathField(
|
||||
default=None,
|
||||
editable=False,
|
||||
max_length=1024,
|
||||
null=True,
|
||||
verbose_name="archive filename",
|
||||
),
|
||||
),
|
||||
(
|
||||
"document",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="versions",
|
||||
to="documents.document",
|
||||
verbose_name="document",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "document version",
|
||||
"verbose_name_plural": "document versions",
|
||||
"ordering": ["-version_number"],
|
||||
},
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="documentversion",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("document", "version_number"),
|
||||
name="documents_documentversion_doc_number_uniq",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1,37 +0,0 @@
|
||||
# Generated by Django 5.1.6 on 2025-02-26 17:08
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0011_alter_workflowaction_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="document",
|
||||
name="root_document",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="versions",
|
||||
to="documents.document",
|
||||
verbose_name="root document for this version",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="document",
|
||||
name="version_label",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="Optional short label for a document version.",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="version label",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -6,7 +6,7 @@ from django.db import models
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0012_document_root_document"),
|
||||
("documents", "0012_add_document_version"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# Generated by Django 5.2.11 on 2026-03-02 17:48
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0014_savedview_visibility_to_ui_settings"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="document",
|
||||
name="version_index",
|
||||
field=models.PositiveIntegerField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="Index of this version within the root document.",
|
||||
null=True,
|
||||
verbose_name="version index",
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="document",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(
|
||||
("root_document__isnull", False),
|
||||
("version_index__isnull", False),
|
||||
),
|
||||
fields=("root_document", "version_index"),
|
||||
name="documents_document_root_version_index_uniq",
|
||||
),
|
||||
),
|
||||
]
|
||||
+1
-1
@@ -100,7 +100,7 @@ def recompute_checksums(apps, schema_editor):
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0015_document_version_index_and_more"),
|
||||
("documents", "0014_savedview_visibility_to_ui_settings"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
+1
-1
@@ -28,7 +28,7 @@ def migrate_fulltext_query_field_prefixes(apps, schema_editor):
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0016_sha256_checksums"),
|
||||
("documents", "0015_sha256_checksums"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
+1
-1
@@ -22,7 +22,7 @@ def migrate_saved_view_rules_forward(apps, schema_editor):
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0017_migrate_fulltext_query_field_prefixes"),
|
||||
("documents", "0016_migrate_fulltext_query_field_prefixes"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@@ -6,8 +6,8 @@ pytestmark = pytest.mark.search
|
||||
|
||||
|
||||
class TestMigrateFulltextQueryFieldPrefixes(TestMigrations):
|
||||
migrate_from = "0016_sha256_checksums"
|
||||
migrate_to = "0017_migrate_fulltext_query_field_prefixes"
|
||||
migrate_from = "0015_sha256_checksums"
|
||||
migrate_to = "0016_migrate_fulltext_query_field_prefixes"
|
||||
|
||||
def setUpBeforeMigration(self, apps) -> None:
|
||||
User = apps.get_model("auth", "User")
|
||||
|
||||
@@ -17,8 +17,8 @@ def _sha256(data: bytes) -> str:
|
||||
class TestSha256ChecksumDataMigration(TestMigrations):
|
||||
"""recompute_checksums correctly updates document checksums from MD5 to SHA256."""
|
||||
|
||||
migrate_from = "0015_document_version_index_and_more"
|
||||
migrate_to = "0016_sha256_checksums"
|
||||
migrate_from = "0014_savedview_visibility_to_ui_settings"
|
||||
migrate_to = "0015_sha256_checksums"
|
||||
reset_sequences = True
|
||||
|
||||
ORIGINAL_CONTENT = b"original file content for sha256 migration test"
|
||||
|
||||
Reference in New Issue
Block a user