Skip to content

Commit 06bb5fa

Browse files
authored
Change unique name restriction on dataset models (#25)
* Change unique name restriction on dataset models * Lint code
1 parent e35f52b commit 06bb5fa

File tree

4 files changed

+183
-64
lines changed

4 files changed

+183
-64
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Generated by Django 5.2.5 on 2025-10-09 12:30
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("datasets", "0012_tabulardataset_unit"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="rasterdataset",
15+
name="name",
16+
field=models.CharField(max_length=155),
17+
),
18+
migrations.AlterField(
19+
model_name="tabulardataset",
20+
name="name",
21+
field=models.CharField(max_length=155),
22+
),
23+
migrations.AlterField(
24+
model_name="vectordataset",
25+
name="name",
26+
field=models.CharField(max_length=155),
27+
),
28+
migrations.AlterUniqueTogether(
29+
name="rasterdataset",
30+
unique_together={("name", "type")},
31+
),
32+
migrations.AlterUniqueTogether(
33+
name="tabulardataset",
34+
unique_together={("name", "type")},
35+
),
36+
migrations.AlterUniqueTogether(
37+
name="vectordataset",
38+
unique_together={("name", "type")},
39+
),
40+
]

vbos/datasets/models.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def delete_raster_file(sender, instance, **kwargs):
8181

8282

8383
class RasterDataset(models.Model):
84-
name = models.CharField(max_length=155, unique=True)
84+
name = models.CharField(max_length=155)
8585
created = models.DateTimeField(auto_now_add=True)
8686
updated = models.DateTimeField(auto_now=True)
8787
cluster = models.ForeignKey(
@@ -97,10 +97,11 @@ def __str__(self):
9797

9898
class Meta:
9999
ordering = ["id"]
100+
unique_together = ["name", "type"]
100101

101102

102103
class VectorDataset(models.Model):
103-
name = models.CharField(max_length=155, unique=True)
104+
name = models.CharField(max_length=155, unique=False)
104105
created = models.DateTimeField(auto_now_add=True)
105106
updated = models.DateTimeField(auto_now=True)
106107
cluster = models.ForeignKey(
@@ -115,6 +116,7 @@ def __str__(self):
115116

116117
class Meta:
117118
ordering = ["id"]
119+
unique_together = ["name", "type"]
118120

119121

120122
class VectorItem(models.Model):
@@ -138,7 +140,7 @@ class Meta:
138140

139141

140142
class TabularDataset(models.Model):
141-
name = models.CharField(max_length=155, unique=True)
143+
name = models.CharField(max_length=155, unique=False)
142144
created = models.DateTimeField(auto_now_add=True)
143145
updated = models.DateTimeField(auto_now=True)
144146
cluster = models.ForeignKey(
@@ -154,6 +156,7 @@ def __str__(self):
154156

155157
class Meta:
156158
ordering = ["id"]
159+
unique_together = ["name", "type"]
157160

158161

159162
class TabularItem(models.Model):

vbos/datasets/test/test_models.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
from django.db.models.deletion import ProtectedError
2+
from django.db.utils import IntegrityError
3+
from django.test import TestCase
4+
from django.core.files.uploadedfile import SimpleUploadedFile
5+
from django.core.exceptions import ValidationError
6+
7+
from vbos.datasets.models import (
8+
Cluster,
9+
RasterDataset,
10+
RasterFile,
11+
TabularDataset,
12+
VectorDataset,
13+
)
14+
15+
16+
class TestRasterModels(TestCase):
17+
def setUp(self):
18+
self.valid_file = SimpleUploadedFile(
19+
"rainfall.tiff", b"file_content", content_type="image/tiff"
20+
)
21+
self.r_1 = RasterFile.objects.create(name="Rainfall COG", file=self.valid_file)
22+
self.r_2 = RasterFile.objects.create(
23+
name="Coastline COG", file="raster/coastline.tiff"
24+
)
25+
self.dataset = RasterDataset.objects.create(
26+
name="Rainfall",
27+
cluster=Cluster.objects.create(name="Environment"),
28+
file=self.r_1,
29+
)
30+
31+
def test_deletion(self):
32+
# RasterFile can't be deleted if it's associates with a dataset
33+
with self.assertRaises(ProtectedError):
34+
self.r_1.delete()
35+
36+
# name should be unique
37+
raster = RasterFile(name="Rainfall COG 2", file="raster/coastline.tiff")
38+
with self.assertRaises(ValidationError):
39+
raster.full_clean()
40+
41+
# file path should be unique
42+
raster = RasterFile(name="Rainfall COG", file="newfile.tif")
43+
with self.assertRaises(ValidationError):
44+
raster.full_clean()
45+
46+
# modify dataset
47+
self.dataset.file = self.r_2
48+
self.dataset.save()
49+
# delete file
50+
self.r_1.delete()
51+
self.assertEqual(RasterFile.objects.count(), 1)
52+
# delete dataset
53+
self.dataset.delete()
54+
self.assertEqual(RasterDataset.objects.count(), 0)
55+
# delete remaining file
56+
self.r_2.delete()
57+
self.assertEqual(RasterFile.objects.count(), 0)
58+
59+
# test file extension validation
60+
invalid_file = SimpleUploadedFile(
61+
"test.jpg", b"file_content", content_type="image/jpeg"
62+
)
63+
raster = RasterFile(name="Test", file=invalid_file)
64+
with self.assertRaises(ValidationError):
65+
raster.full_clean()
66+
67+
RasterFile.objects.all().delete()
68+
69+
def test_unique_name_type(self):
70+
self.cluster = Cluster.objects.create(name="Administrative")
71+
r_2 = RasterFile.objects.create(
72+
name="Population Density COG", file="raster/pop.tiff"
73+
)
74+
RasterDataset.objects.create(
75+
name="Population",
76+
cluster=self.cluster,
77+
source="Government",
78+
file=r_2,
79+
)
80+
RasterDataset.objects.create(
81+
name="Population",
82+
cluster=self.cluster,
83+
source="Government",
84+
file=r_2,
85+
type="estimated_damage",
86+
)
87+
with self.assertRaises(IntegrityError):
88+
RasterDataset.objects.create(
89+
name="Population",
90+
cluster=self.cluster,
91+
source="Government",
92+
file=r_2,
93+
)
94+
95+
96+
class TestTabularDatasetModel(TestCase):
97+
def test_unique_name_type(self):
98+
self.cluster = Cluster.objects.create(name="Administrative")
99+
TabularDataset.objects.create(
100+
name="Population",
101+
cluster=self.cluster,
102+
source="Government",
103+
)
104+
TabularDataset.objects.create(
105+
name="Population",
106+
cluster=self.cluster,
107+
source="Government",
108+
type="estimated_damage",
109+
)
110+
with self.assertRaises(IntegrityError):
111+
TabularDataset.objects.create(
112+
name="Population",
113+
cluster=self.cluster,
114+
source="Government",
115+
)
116+
117+
118+
class TestVectorDatasetModel(TestCase):
119+
def test_unique_name_type(self):
120+
self.cluster = Cluster.objects.create(name="Administrative")
121+
VectorDataset.objects.create(
122+
name="Population",
123+
cluster=self.cluster,
124+
source="Government",
125+
)
126+
VectorDataset.objects.create(
127+
name="Population",
128+
cluster=self.cluster,
129+
source="Government",
130+
type="estimated_damage",
131+
)
132+
with self.assertRaises(IntegrityError):
133+
VectorDataset.objects.create(
134+
name="Population",
135+
cluster=self.cluster,
136+
source="Government",
137+
)

vbos/datasets/test/test_raster_models.py

Lines changed: 0 additions & 61 deletions
This file was deleted.

0 commit comments

Comments
 (0)