From a4def5dca885e86f6a60e7202fd9f5b7e34b5025 Mon Sep 17 00:00:00 2001 From: Mike Chagnon Date: Tue, 3 Sep 2024 20:23:06 -0700 Subject: [PATCH 1/2] 411: add unique constraint on data directory path --- .../management/commands/adddirectory.py | 7 +++++++ .../0036_datadirectory_unique_path.py | 17 +++++++++++++++++ ifcbdb/dashboard/models.py | 5 +++++ 3 files changed, 29 insertions(+) create mode 100644 ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py diff --git a/ifcbdb/dashboard/management/commands/adddirectory.py b/ifcbdb/dashboard/management/commands/adddirectory.py index 57a5db6e..b39243a8 100644 --- a/ifcbdb/dashboard/management/commands/adddirectory.py +++ b/ifcbdb/dashboard/management/commands/adddirectory.py @@ -30,6 +30,13 @@ def handle(self, *args, **options): except Dataset.DoesNotExist: self.stderr.write('No such dataset "{}"'.format(dataset_name)) return + + # make sure the directory path is not already in the database + existing_path = DataDirectory.objects.filter(path=path).first() + if existing_path: + self.stderr.write('Path "{}" is already in use by dataset "{}"'.format(path, existing_path.dataset.name)) + return + # create the directory dd = DataDirectory(path=path, kind=kind) dd.dataset = d diff --git a/ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py b/ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py new file mode 100644 index 00000000..327341f6 --- /dev/null +++ b/ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.14 on 2024-09-04 03:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dashboard', '0035_auto_20191114_2039'), + ] + + operations = [ + migrations.AddConstraint( + model_name='datadirectory', + constraint=models.UniqueConstraint(fields=('path',), name='unique path'), + ), + ] diff --git a/ifcbdb/dashboard/models.py b/ifcbdb/dashboard/models.py index de1aad16..fef4b504 100644 --- a/ifcbdb/dashboard/models.py +++ b/ifcbdb/dashboard/models.py @@ -393,6 +393,11 @@ def get_class_scores_directory(self): def __str__(self): return '{} ({})'.format(self.path, self.kind) + class Meta: + constraints = [ + models.UniqueConstraint(fields=['path'], name='unique path') + ] + class Bin(models.Model): # bin's permanent identifier (e.g., D20190102T1234_IFCB927) pid = models.CharField(max_length=64, unique=True) From 74ddc16476c7dffe3edc86e52e109f69865dfde0 Mon Sep 17 00:00:00 2001 From: Mike Chagnon Date: Wed, 16 Oct 2024 12:35:11 -0700 Subject: [PATCH 2/2] 411: make path unique with datasets and not globally --- .../management/commands/adddirectory.py | 2 +- .../0036_datadirectory_unique_path.py | 4 ++-- ifcbdb/dashboard/models.py | 2 +- ifcbdb/secure/forms.py | 18 ++++++++++++++++++ ifcbdb/secure/views.py | 2 +- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/ifcbdb/dashboard/management/commands/adddirectory.py b/ifcbdb/dashboard/management/commands/adddirectory.py index b39243a8..df00750a 100644 --- a/ifcbdb/dashboard/management/commands/adddirectory.py +++ b/ifcbdb/dashboard/management/commands/adddirectory.py @@ -32,7 +32,7 @@ def handle(self, *args, **options): return # make sure the directory path is not already in the database - existing_path = DataDirectory.objects.filter(path=path).first() + existing_path = DataDirectory.objects.filter(dataset=d, path=path).first() if existing_path: self.stderr.write('Path "{}" is already in use by dataset "{}"'.format(path, existing_path.dataset.name)) return diff --git a/ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py b/ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py index 327341f6..cfc2c437 100644 --- a/ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py +++ b/ifcbdb/dashboard/migrations/0036_datadirectory_unique_path.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.14 on 2024-09-04 03:13 +# Generated by Django 4.2.14 on 2024-10-16 18:52 from django.db import migrations, models @@ -12,6 +12,6 @@ class Migration(migrations.Migration): operations = [ migrations.AddConstraint( model_name='datadirectory', - constraint=models.UniqueConstraint(fields=('path',), name='unique path'), + constraint=models.UniqueConstraint(fields=('dataset', 'path'), name='unique path'), ), ] diff --git a/ifcbdb/dashboard/models.py b/ifcbdb/dashboard/models.py index fef4b504..f9e79c21 100644 --- a/ifcbdb/dashboard/models.py +++ b/ifcbdb/dashboard/models.py @@ -395,7 +395,7 @@ def __str__(self): class Meta: constraints = [ - models.UniqueConstraint(fields=['path'], name='unique path') + models.UniqueConstraint(fields=['dataset', 'path'], name='unique path') ] class Bin(models.Model): diff --git a/ifcbdb/secure/forms.py b/ifcbdb/secure/forms.py index 30fea962..4a9b0cb6 100644 --- a/ifcbdb/secure/forms.py +++ b/ifcbdb/secure/forms.py @@ -67,6 +67,11 @@ def save(self, commit=True): class DirectoryForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + self.dataset_id = kwargs.pop("dataset_id", None) + + super().__init__(*args, **kwargs) + def clean_path(self): path = self.cleaned_data["path"] @@ -91,6 +96,19 @@ def clean_blacklist(self): return ",".join([name.strip() for name in blacklist.split(",")]) + def clean(self): + data = self.cleaned_data + path = self.cleaned_data.get("path") + + # make sure the directory path is not already in the database + existing_path = DataDirectory.objects.filter(dataset_id=self.dataset_id, path=path).first() + if existing_path: + raise forms.ValidationError({ + 'path': 'Path "{}" is already in use'.format(path) + }) + + return data + def _match_folder_names(self, value): return re.match(r'^[A-Za-z0-9,\s]*$', value) diff --git a/ifcbdb/secure/views.py b/ifcbdb/secure/views.py index 27a150cc..6abfa92a 100644 --- a/ifcbdb/secure/views.py +++ b/ifcbdb/secure/views.py @@ -96,7 +96,7 @@ def edit_directory(request, dataset_id, id): directory.version = DataDirectory.DEFAULT_VERSION if request.POST: - form = DirectoryForm(request.POST, instance=directory) + form = DirectoryForm(request.POST, instance=directory, dataset_id=dataset_id) if form.is_valid(): instance = form.save(commit=False) if instance.kind == "raw":