mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Change model uniqueness from name to name+owner
This commit is contained in:
parent
2fe7f8be46
commit
b382f1412a
@ -0,0 +1,107 @@
|
||||
# Generated by Django 4.1.5 on 2023-03-04 22:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("documents", "1032_alter_correspondent_matching_algorithm_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="documenttype",
|
||||
options={
|
||||
"ordering": ("name",),
|
||||
"verbose_name": "document type",
|
||||
"verbose_name_plural": "document types",
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name="tag",
|
||||
options={
|
||||
"ordering": ("name",),
|
||||
"verbose_name": "tag",
|
||||
"verbose_name_plural": "tags",
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="correspondent",
|
||||
name="name",
|
||||
field=models.CharField(max_length=128, verbose_name="name"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="documenttype",
|
||||
name="name",
|
||||
field=models.CharField(max_length=128, verbose_name="name"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="storagepath",
|
||||
name="name",
|
||||
field=models.CharField(max_length=128, verbose_name="name"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="tag",
|
||||
name="name",
|
||||
field=models.CharField(max_length=128, verbose_name="name"),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="correspondent",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("name", "owner"),
|
||||
name="documents_correspondent_unique_name_owner",
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="correspondent",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(("owner__isnull", True)),
|
||||
fields=("name",),
|
||||
name="documents_correspondent_name_uniq",
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="documenttype",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("name", "owner"),
|
||||
name="documents_documenttype_unique_name_owner",
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="documenttype",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(("owner__isnull", True)),
|
||||
fields=("name",),
|
||||
name="documents_documenttype_name_uniq",
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="storagepath",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("name", "owner"), name="documents_storagepath_unique_name_owner"
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="storagepath",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(("owner__isnull", True)),
|
||||
fields=("name",),
|
||||
name="documents_storagepath_name_uniq",
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="tag",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("name", "owner"), name="documents_tag_unique_name_owner"
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="tag",
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(("owner__isnull", True)),
|
||||
fields=("name",),
|
||||
name="documents_tag_name_uniq",
|
||||
),
|
||||
),
|
||||
]
|
@ -23,7 +23,20 @@ ALL_STATES = sorted(states.ALL_STATES)
|
||||
TASK_STATE_CHOICES = sorted(zip(ALL_STATES, ALL_STATES))
|
||||
|
||||
|
||||
class MatchingModel(models.Model):
|
||||
class ModelWithOwner(models.Model):
|
||||
owner = models.ForeignKey(
|
||||
User,
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_("owner"),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class MatchingModel(ModelWithOwner):
|
||||
|
||||
MATCH_NONE = 0
|
||||
MATCH_ANY = 1
|
||||
@ -43,7 +56,7 @@ class MatchingModel(models.Model):
|
||||
(MATCH_AUTO, _("Automatic")),
|
||||
)
|
||||
|
||||
name = models.CharField(_("name"), max_length=128, unique=True)
|
||||
name = models.CharField(_("name"), max_length=128)
|
||||
|
||||
match = models.CharField(_("match"), max_length=256, blank=True)
|
||||
|
||||
@ -58,32 +71,29 @@ class MatchingModel(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
ordering = ("name",)
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["name", "owner"],
|
||||
name="%(app_label)s_%(class)s_unique_name_owner",
|
||||
),
|
||||
models.UniqueConstraint(
|
||||
name="%(app_label)s_%(class)s_name_uniq",
|
||||
fields=["name"],
|
||||
condition=models.Q(owner__isnull=True),
|
||||
),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ModelWithOwner(models.Model):
|
||||
owner = models.ForeignKey(
|
||||
User,
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_("owner"),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class Correspondent(MatchingModel, ModelWithOwner):
|
||||
class Meta:
|
||||
ordering = ("name",)
|
||||
class Correspondent(MatchingModel):
|
||||
class Meta(MatchingModel.Meta):
|
||||
verbose_name = _("correspondent")
|
||||
verbose_name_plural = _("correspondents")
|
||||
|
||||
|
||||
class Tag(MatchingModel, ModelWithOwner):
|
||||
class Tag(MatchingModel):
|
||||
|
||||
color = models.CharField(_("color"), max_length=7, default="#a6cee3")
|
||||
|
||||
@ -96,25 +106,24 @@ class Tag(MatchingModel, ModelWithOwner):
|
||||
),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
class Meta(MatchingModel.Meta):
|
||||
verbose_name = _("tag")
|
||||
verbose_name_plural = _("tags")
|
||||
|
||||
|
||||
class DocumentType(MatchingModel, ModelWithOwner):
|
||||
class Meta:
|
||||
class DocumentType(MatchingModel):
|
||||
class Meta(MatchingModel.Meta):
|
||||
verbose_name = _("document type")
|
||||
verbose_name_plural = _("document types")
|
||||
|
||||
|
||||
class StoragePath(MatchingModel, ModelWithOwner):
|
||||
class StoragePath(MatchingModel):
|
||||
path = models.CharField(
|
||||
_("path"),
|
||||
max_length=512,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ("name",)
|
||||
class Meta(MatchingModel.Meta):
|
||||
verbose_name = _("storage path")
|
||||
verbose_name_plural = _("storage paths")
|
||||
|
||||
|
@ -186,6 +186,18 @@ class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin):
|
||||
def update(self, instance, validated_data):
|
||||
if "set_permissions" in validated_data:
|
||||
self._set_permissions(validated_data["set_permissions"], instance)
|
||||
if "owner" in validated_data and "name" in self.Meta.fields:
|
||||
name = validated_data["name"] if "name" in validated_data else instance.name
|
||||
print(name)
|
||||
not_unique = (
|
||||
self.Meta.model.objects.exclude(pk=instance.pk)
|
||||
.filter(owner=validated_data["owner"], name=name)
|
||||
.exists()
|
||||
)
|
||||
if not_unique:
|
||||
raise serializers.ValidationError(
|
||||
"Object violates owner / name unique constraint",
|
||||
)
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user