Skip to content

Commit a6305fc

Browse files
committed
Make Report and Photo primary keys UUIDField.
1 parent 562bae4 commit a6305fc

34 files changed

+860
-236
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,6 @@ Session.vim
265265
# Temporary
266266
.netrwhist
267267

268-
# Auto-generated tag files
269-
tags
270-
271268
# Redis dump file
272269
dump.rdb
273270

config/settings/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@
110110
"mosquito_alert.images",
111111
"mosquito_alert.individuals",
112112
"mosquito_alert.moderation",
113-
"mosquito_alert.moderation.apps.FlagConfig",
114113
"mosquito_alert.notifications",
115114
"mosquito_alert.reports",
115+
"mosquito_alert.tags",
116116
"mosquito_alert.taxa",
117117
"mosquito_alert.users",
118118
]

mosquito_alert/geo/tests/test_models.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -518,10 +518,10 @@ def test_location_is_deleted_on_self_delete(self):
518518
loc = LocationFactory()
519519
geo_loc = self.factory_cls(location=loc)
520520

521-
assert Location.objects.all().count() == 1
522-
523521
geo_loc.delete()
524-
assert Location.objects.all().count() == 0
522+
523+
with pytest.raises(Location.DoesNotExist):
524+
Location.objects.get(pk=loc.pk)
525525

526526

527527
@pytest.mark.django_db
Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Generated by Django 4.0.8 on 2023-03-01 13:06
22

3+
import uuid
4+
35
from django.conf import settings
46
from django.db import migrations, models
57
import django.db.models.deletion
@@ -8,7 +10,6 @@
810

911

1012
class Migration(migrations.Migration):
11-
1213
initial = True
1314

1415
dependencies = [
@@ -17,18 +18,32 @@ class Migration(migrations.Migration):
1718

1819
operations = [
1920
migrations.CreateModel(
20-
name='Photo',
21+
name="Photo",
2122
fields=[
22-
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
23-
('image', mosquito_alert.images.fields.ProcessedImageField(upload_to=mosquito_alert.images.models.image_upload_to)),
24-
('created_at', models.DateTimeField(auto_now_add=True)),
25-
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photos', to=settings.AUTH_USER_MODEL)),
23+
("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
24+
(
25+
"image",
26+
mosquito_alert.images.fields.ProcessedImageField(
27+
upload_to=mosquito_alert.images.models.image_upload_to
28+
),
29+
),
30+
("created_at", models.DateTimeField(auto_now_add=True)),
31+
(
32+
"user",
33+
models.ForeignKey(
34+
blank=True,
35+
null=True,
36+
on_delete=django.db.models.deletion.SET_NULL,
37+
related_name="photos",
38+
to=settings.AUTH_USER_MODEL,
39+
),
40+
),
2641
],
2742
options={
28-
'verbose_name': 'photo',
29-
'verbose_name_plural': 'photos',
30-
'ordering': ['-created_at'],
31-
'permissions': [('view_exif', 'Can view exif metadata')],
43+
"verbose_name": "photo",
44+
"verbose_name_plural": "photos",
45+
"ordering": ["-created_at"],
46+
"permissions": [("view_exif", "Can view exif metadata")],
3247
},
3348
),
3449
]

mosquito_alert/images/models.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import uuid
3-
from pathlib import Path
43

54
from django.conf import settings
65
from django.db import models
@@ -20,17 +19,13 @@ def image_upload_to(instance, filename):
2019
# a recommended extension is already found in the filename
2120
_, ext = os.path.splitext(filename)
2221

23-
# Checking if filename is already a valid UUID.
24-
# Using it if it is valid.
25-
try:
26-
uuid_str = uuid.UUID(hex=Path(filename).stem, version=4)
27-
except ValueError:
28-
# Creating a new uuid
29-
uuid_str = uuid.uuid4()
30-
return os.path.join("images", f"{uuid_str}{ext}")
22+
return os.path.join("images", f"{instance.id}{ext}")
3123

3224

25+
# NOTE: FlagModeratedModel uses UUID as pk
3326
class Photo(FlagModeratedModel, TimeStampedModel):
27+
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
28+
3429
# Relations
3530
user = models.ForeignKey(
3631
settings.AUTH_USER_MODEL,
@@ -90,4 +85,4 @@ class Meta(FlagModeratedModel.Meta, TimeStampedModel.Meta):
9085
]
9186

9287
def __str__(self):
93-
return os.path.basename(self.image.name)
88+
return str(self.id)

mosquito_alert/images/tests/factories.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import factory
2-
from factory.django import DjangoModelFactory, ImageField
2+
from factory.django import ImageField
33

4+
from mosquito_alert.moderation.tests.factories import BaseFlagModeratedModelFactory
45
from mosquito_alert.users.tests.factories import UserFactory
56

67
from ..models import Photo
78

89

9-
class PhotoFactory(DjangoModelFactory):
10+
class PhotoFactory(BaseFlagModeratedModelFactory):
1011
user = factory.SubFactory(UserFactory)
1112
image = ImageField()
1213

mosquito_alert/images/tests/test_admin.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ def test_add(self, client, admin_user):
4444
url,
4545
data={
4646
"image": image,
47-
"flag-flag-content_type-object_id-TOTAL_FORMS": "0",
48-
"flag-flag-content_type-object_id-INITIAL_FORMS": "0",
49-
"flag-flag-content_type-object_id-empty-flags-TOTAL_FORMS": "0",
50-
"flag-flag-content_type-object_id-empty-flags-INITIAL_FORMS": "0",
47+
"moderation-flag-content_type-object_id-TOTAL_FORMS": "0",
48+
"moderation-flag-content_type-object_id-INITIAL_FORMS": "0",
49+
"moderation-flag-content_type-object_id-empty-flags-TOTAL_FORMS": "0",
50+
"moderation-flag-content_type-object_id-empty-flags-INITIAL_FORMS": "0",
5151
"photo_identification_tasks-TOTAL_FORMS": "0",
5252
"photo_identification_tasks-INITIAL_FORMS": "0",
5353
},

mosquito_alert/images/tests/test_models.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import os
2+
import uuid
23

34
import pytest
45
from django.db import models
56
from PIL import Image
67

8+
from mosquito_alert.moderation.tests.test_models import BaseTestFlagModeratedModel
79
from mosquito_alert.utils.tests.test_models import BaseTestTimeStampedModel
810

911
from ..models import Photo
@@ -12,7 +14,7 @@
1214

1315

1416
@pytest.mark.django_db
15-
class TestPhoto(BaseTestTimeStampedModel):
17+
class TestPhoto(BaseTestFlagModeratedModel, BaseTestTimeStampedModel):
1618
model = Photo
1719
factory_cls = PhotoFactory
1820

@@ -34,17 +36,11 @@ def test_image_is_uploaded_in_images_path(self):
3436
p = self.factory_cls()
3537
assert os.path.dirname(p.image.name) == "images"
3638

37-
def test_image_filaname_is_replaced_to_uuid(self, mocker):
38-
mocker.patch("uuid.uuid4", return_value="mocked_uuid")
39-
40-
p = self.factory_cls(image__filename="example.jpg")
41-
filename, _ = os.path.splitext(os.path.basename(p.image.name))
42-
assert filename == "mocked_uuid"
43-
44-
def test_image_filename_is_kept_if_already_uuid(self):
45-
p = self.factory_cls(image__filename="5c240771-4f46-4d0b-972e-a2c0edd31451.png")
39+
def test_image_filaname_is_replaced_to_uuid_from_id(self):
40+
new_uuid = uuid.uuid4()
41+
p = self.factory_cls(id=new_uuid, image__filename="example.jpg")
4642
filename, _ = os.path.splitext(os.path.basename(p.image.name))
47-
assert filename == "5c240771-4f46-4d0b-972e-a2c0edd31451"
43+
assert filename == str(new_uuid)
4844

4945
def test_image_is_converted_to_webp(self):
5046
assert self.model._meta.get_field("image")._original_spec.format == "WEBP"
@@ -145,5 +141,7 @@ def test_default_orderding_shows_newest_first(self):
145141
assert self.model._meta.ordering == ["-created_at"]
146142

147143
def test__str__(self):
148-
p = self.factory_cls(image__filename="5c240771-4f46-4d0b-972e-a2c0edd31451.webp")
149-
assert p.__str__() == "5c240771-4f46-4d0b-972e-a2c0edd31451.webp"
144+
new_uuid = uuid.uuid4()
145+
146+
p = self.factory_cls(id=new_uuid)
147+
assert p.__str__() == str(new_uuid)

mosquito_alert/moderation/admin.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from django.contrib.admin.options import InlineModelAdmin
22
from django.contrib.contenttypes.admin import GenericInlineModelAdmin
3-
from flag.models import Flag, FlagInstance
43
from nested_admin.nested import NestedGenericTabularInlineMixin, NestedTabularInlineMixin
54

5+
from .models import Flag, FlagInstance
6+
67

78
class FlagInstanceInlineAdmin(InlineModelAdmin):
89
model = FlagInstance

mosquito_alert/moderation/apps.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
from django.apps import AppConfig
2-
from flag.apps import FlagConfig as OriginalFlagConfig
3-
4-
5-
class FlagConfig(OriginalFlagConfig):
6-
# Overriding FlagConfig to avoid extra migrations when running makemigrations.
7-
default_auto_field = "django.db.models.AutoField"
82

93

104
class ModerationConfig(AppConfig):

0 commit comments

Comments
 (0)