photo-objects 0.0.7__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,6 @@
1
+ import re
2
+
3
+ from django.contrib.sites.models import Site
1
4
  from django.db.models.deletion import ProtectedError
2
5
  from django.http import HttpRequest
3
6
 
@@ -13,6 +16,24 @@ from .utils import (
13
16
  )
14
17
 
15
18
 
19
+ def get_site_album(site: Site) -> Album:
20
+ album_key = f'_site_{site.id}'
21
+ return Album.objects.get_or_create(
22
+ key=album_key,
23
+ defaults={
24
+ 'title': site.name,
25
+ 'visibility': Album.Visibility.ADMIN,
26
+ })
27
+
28
+
29
+ def parse_site_id(album_key: str) -> int | None:
30
+ key_match = re.match(r'_site_([0-9]+)', album_key)
31
+ if not key_match:
32
+ return None
33
+
34
+ return int(key_match.group(1))
35
+
36
+
16
37
  def get_albums(request: HttpRequest):
17
38
  if not request.user.is_authenticated:
18
39
  return Album.objects.filter(visibility=Album.Visibility.PUBLIC)
@@ -1,6 +1,7 @@
1
1
  from django.core.management.base import BaseCommand
2
2
  from django.contrib.sites.models import Site
3
3
 
4
+ from photo_objects.django.api.album import get_site_album
4
5
  from photo_objects.django.models import Album
5
6
 
6
7
 
@@ -11,18 +12,13 @@ class Command(BaseCommand):
11
12
  sites = Site.objects.all()
12
13
 
13
14
  for site in sites:
14
- album_key = f'_site_{site.id}'
15
- _, created = Album.objects.get_or_create(
16
- key=album_key,
17
- defaults={
18
- 'visibility': Album.Visibility.ADMIN,
19
- })
20
-
15
+ album, created = get_site_album(site)
21
16
  if created:
22
17
  self.stdout.write(
23
18
  self.style.SUCCESS(
24
19
  f'Album for site {site.domain} created:') +
25
- f'\n Key: {album_key}')
20
+ f'\n Key: {album.key}'
21
+ f'\n Title: {album.title}')
26
22
  else:
27
23
  self.stdout.write(
28
24
  self.style.NOTICE(
@@ -1,7 +1,11 @@
1
+ import re
2
+
3
+ from django.contrib.sites.models import Site
1
4
  from django.db.models.signals import post_save, post_delete
2
5
  from django.dispatch import receiver
3
6
 
4
- from .models import Photo
7
+ from .api.album import parse_site_id, get_site_album
8
+ from .models import Album, Photo
5
9
 
6
10
 
7
11
  @receiver(post_save, sender=Photo)
@@ -56,3 +60,30 @@ def update_album_on_photo_delete(sender, **kwargs):
56
60
 
57
61
  if needs_save:
58
62
  album.save()
63
+
64
+
65
+ @receiver(post_save, sender=Site)
66
+ def update_album_on_site_save(sender, **kwargs):
67
+ site = kwargs.get('instance', None)
68
+ album, created = get_site_album(site)
69
+
70
+ if not created and album.title != site.name:
71
+ album.title = site.name
72
+ album.save()
73
+
74
+
75
+ @receiver(post_save, sender=Album)
76
+ def update_site_on_album_save(sender, **kwargs):
77
+ album = kwargs.get('instance', None)
78
+ site_id = parse_site_id(album.key)
79
+ if site_id is None:
80
+ return
81
+
82
+ try:
83
+ site = Site.objects.get(id=site_id)
84
+ except Site.DoesNotExist:
85
+ return
86
+
87
+ if site.name != album.title:
88
+ site.name = album.title
89
+ site.save()
@@ -3,6 +3,7 @@ from time import sleep
3
3
 
4
4
  from django.contrib.auth import get_user_model
5
5
  from django.contrib.auth.models import Permission
6
+ from django.contrib.sites.models import Site
6
7
 
7
8
  from photo_objects.django.models import Album
8
9
  from photo_objects.img import utcnow
@@ -375,3 +376,25 @@ class AlbumViewTests(TestCase):
375
376
 
376
377
  response = self.client.delete("/api/albums/copenhagen")
377
378
  self.assertStatus(response, 204)
379
+
380
+ def test_site_config_album_title_change(self):
381
+ site = Site.objects.get(id=1)
382
+ album, _ = Album.objects.get_or_create(
383
+ key="_site_1",
384
+ defaults={
385
+ "title": "Site 1",
386
+ "visibility": Album.Visibility.ADMIN,
387
+ }
388
+ )
389
+
390
+ site.name = "Changed in site"
391
+ site.save()
392
+
393
+ album.refresh_from_db()
394
+ self.assertEqual(album.title, "Changed in site")
395
+
396
+ album.title = "Changed in album"
397
+ album.save()
398
+
399
+ site.refresh_from_db()
400
+ self.assertEqual(site.name, "Changed in album")
@@ -6,6 +6,7 @@ from django.urls import reverse
6
6
  from django.utils.translation import gettext_lazy as _
7
7
 
8
8
  from photo_objects.django import api
9
+ from photo_objects.django.api.album import parse_site_id
9
10
  from photo_objects.django.api.utils import FormValidationFailed
10
11
  from photo_objects.django.forms import CreateAlbumForm, ModifyAlbumForm
11
12
  from photo_objects.django.models import Album
@@ -48,12 +49,15 @@ def new_album(request: HttpRequest):
48
49
 
49
50
 
50
51
  def get_info(request: HttpRequest, album_key: str):
51
- if re.match(r'_site_[0-9]+', album_key) and request.site:
52
+ site_id = parse_site_id(album_key)
53
+ if site_id is not None and request.site:
52
54
  return (
53
55
  "This is a special album for configuring site metadata for "
54
56
  f"{request.site.name}. Use album title to override the site name, "
55
57
  "albums cover photo to configure the preview image, and album "
56
- "description to configure the site description.")
58
+ "description to configure the site description. The album title "
59
+ "is automatically updated when the related sites name is changed "
60
+ "and vice versa.")
57
61
 
58
62
 
59
63
  @json_problem_as_html
@@ -44,7 +44,7 @@ def uses_https(request: HttpRequest) -> Validation:
44
44
  detail += _(
45
45
  ' If you are running the API server behind a reverse proxy or '
46
46
  'a load-balancer, ensure that HTTPS termination is configured '
47
- f'correctly. ({request.META})')
47
+ f'correctly.')
48
48
 
49
49
  return Validation(
50
50
  check=_("Site is served over HTTPS"),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: photo-objects
3
- Version: 0.0.7
3
+ Version: 0.1.0
4
4
  Summary: Application for storing photos in S3 compatible object-storage.
5
5
  Author: Toni Kangas
6
6
  License: MIT License
@@ -9,17 +9,17 @@ photo_objects/django/context_processors.py,sha256=DLhLZHAvGlrpxYegaLiKEx9X7rpyZU
9
9
  photo_objects/django/forms.py,sha256=VoDlyZAwiTLyNxW3rRk5bzjfPJvNuKV-wpuLGCe5TCY,6505
10
10
  photo_objects/django/models.py,sha256=tRHBqswASWMnyz8rwiKsmHDqEvQX54ly9k8tvU7qNOM,4597
11
11
  photo_objects/django/objsto.py,sha256=GZuoPZ1I5qX4rwEYZlOfZZiV4NQ19iknQBT6755421Y,2417
12
- photo_objects/django/signals.py,sha256=Q_Swjl_9z6B6zP-97D_ep5zGSAEgmQfwUz0utMDY93A,1624
12
+ photo_objects/django/signals.py,sha256=NEh_pfvsSt2f7MuHIJE0uLHUkqjKH4ipAFS7tmvm9LI,2400
13
13
  photo_objects/django/urls.py,sha256=safcovG-8G60F_1v31ZvCCtBE8d6sHUtma6d5ZQHymo,2356
14
14
  photo_objects/django/api/__init__.py,sha256=BnEHlm3mwyBy-1xhk-NFasgZa4fjCDjtfkBUoH0puPY,62
15
- photo_objects/django/api/album.py,sha256=ZH8WfEoZ52L_ucMvCaccXf1lU7IrSgtub2sWEMrMpQs,1993
15
+ photo_objects/django/api/album.py,sha256=c5qDvy6ebIZCzggxcYgSgLBR0cco79V47nJf2OHuBj8,2486
16
16
  photo_objects/django/api/auth.py,sha256=LfMm02_TKwrP5XFie-KzBnW3FNFWQAafBlu0UE19Gd4,1370
17
17
  photo_objects/django/api/photo.py,sha256=NGCg_Qd4X9NAd7t6lqByK9JGsoTq8HKkyEr-HwMCimI,3838
18
18
  photo_objects/django/api/utils.py,sha256=DgAsbvLLZxck_D6AXLsvUXJ3OguLufZ8sadmsToenJ4,5245
19
19
  photo_objects/django/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  photo_objects/django/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  photo_objects/django/management/commands/create-initial-admin-account.py,sha256=M4qv1d_qFSGy_lDcKbyKOmfGsQt8i16Zoit9cJ6PwAU,1099
22
- photo_objects/django/management/commands/create-site-albums.py,sha256=t0g1hKVFHoZJoJayGOZUqJaR_z-Bdyt9Ut4ETpOaRjI,1036
22
+ photo_objects/django/management/commands/create-site-albums.py,sha256=mz99RfmczM0x7zuVRabReq4uBZXN-2Ow7VoNWARvBig,959
23
23
  photo_objects/django/migrations/0001_initial.py,sha256=BLW-EZ38sBgDhOYyprc-h_vuPpRxA11qxt4ZuYNO1Wo,2424
24
24
  photo_objects/django/migrations/0002_created_at_updated_at.py,sha256=7OT2VvDffAkX9XKBHVY-jvzxeIl2yU0Jr1ByCNGcUfw,1039
25
25
  photo_objects/django/migrations/0003_admin_visibility.py,sha256=PdxPOJzr-ViRBlOYUHEEGhe0hLtDysZJdMqvbjKVpEg,529
@@ -28,7 +28,7 @@ photo_objects/django/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
28
28
  photo_objects/django/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  photo_objects/django/templatetags/photo_objects_extras.py,sha256=LjqvVZpcVqdEQQ-EgC7OkEv2DqIvmfmDC-EsQNmkY7M,1205
30
30
  photo_objects/django/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- photo_objects/django/tests/test_album.py,sha256=eforhWjaL3ZD7aENrjzbVhXHLI9WpY8pGZRXkgF7yNw,13333
31
+ photo_objects/django/tests/test_album.py,sha256=qeRx_M8EvY9n_as1x8-EWtp9Ob1kOPGnUfZuUnMfDO4,13979
32
32
  photo_objects/django/tests/test_auth.py,sha256=su00EypNzGQcvxqhmOtFevZriK31pY7yD1HxpQFcUT4,3928
33
33
  photo_objects/django/tests/test_photo.py,sha256=SpQsVynzJLP2F9qYrvZMzCBSiHvsRDpOZ8-W_07K_q8,13386
34
34
  photo_objects/django/tests/test_utils.py,sha256=DkhzDtZqu5OXg-IKzqHz2GY0sFS8RbwYC3w81RuPxS4,1259
@@ -41,12 +41,12 @@ photo_objects/django/views/api/auth.py,sha256=N53csbthH0DEMFjY3fqhtLmtdL7xqzkatk
41
41
  photo_objects/django/views/api/photo.py,sha256=52UMP1r6TN_xfu8fHE25yOUiTa6W1F2XbgEichM8tTE,3526
42
42
  photo_objects/django/views/api/utils.py,sha256=uQzKdSKHRAux5OZzqgWQr0gsK_FeweQP0cg_67OWA_Y,264
43
43
  photo_objects/django/views/ui/__init__.py,sha256=vbFXPj5liue-M_CXQGP5PKhD98Z5ev53yKLPU8zWpUs,71
44
- photo_objects/django/views/ui/album.py,sha256=bgFPg9ipkQFqZK7cQgYT9gqpUgdSJ_1NTHlszsfclKU,5010
45
- photo_objects/django/views/ui/configuration.py,sha256=bkckPtQHf7FYwEUIemtMTA1jaDHi7B7VA4ucO_4qt5E,5593
44
+ photo_objects/django/views/ui/album.py,sha256=80fkAdtXjgBqq-4e1i2slnzWD2C-m6rc02piIqYlgmI,5215
45
+ photo_objects/django/views/ui/configuration.py,sha256=pzNRHq3FSrVCTx2R31_FW3A3aJxzEO4pDnXsOVS75uA,5576
46
46
  photo_objects/django/views/ui/photo.py,sha256=4NJSN5X_NcVcUEPaoGEGmXRDAgI5_KsOlHr7j-yo2QY,6040
47
47
  photo_objects/django/views/ui/utils.py,sha256=YV_YcUbX-zUkdFnBlezPChR6aPDhZJ9loSOHBSzF6Cc,273
48
- photo_objects-0.0.7.dist-info/licenses/LICENSE,sha256=V3w6hTjXfP65F4r_mejveHcV5igHrblxao3-2RlfVlA,1068
49
- photo_objects-0.0.7.dist-info/METADATA,sha256=xYOJTlRMBdsnYh_0AHAzGcHybbiUodE4SY8Xvc0E85g,3671
50
- photo_objects-0.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
- photo_objects-0.0.7.dist-info/top_level.txt,sha256=SZeL8mhf-WMGdhRtTGFvZc3aIRBboQls9O0cFDMGdQ0,14
52
- photo_objects-0.0.7.dist-info/RECORD,,
48
+ photo_objects-0.1.0.dist-info/licenses/LICENSE,sha256=V3w6hTjXfP65F4r_mejveHcV5igHrblxao3-2RlfVlA,1068
49
+ photo_objects-0.1.0.dist-info/METADATA,sha256=o0IEDnYB7mXHUO3cT2i-yCDCkfS01DoT8OW32U4tOxU,3671
50
+ photo_objects-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ photo_objects-0.1.0.dist-info/top_level.txt,sha256=SZeL8mhf-WMGdhRtTGFvZc3aIRBboQls9O0cFDMGdQ0,14
52
+ photo_objects-0.1.0.dist-info/RECORD,,