localcosmos-app-kit 0.9.10__py3-none-any.whl → 0.9.11__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.
@@ -99,7 +99,7 @@ class TaxonProfilesJSONBuilder(JSONBuilder):
99
99
 
100
100
  def get_vernacular_name_from_nature_guides(self, lazy_taxon):
101
101
  if lazy_taxon.name_uuid in self.vernacular_names_from_nature_guide_cache:
102
- return self.vernacular_names_from_nature_guide_cache[lazy_taxon.name_uuid]
102
+ return self.vernacular_names_from_nature_guide_cache[str(lazy_taxon.name_uuid)]
103
103
 
104
104
  return lazy_taxon.get_primary_locale_vernacular_name_from_nature_guides(self.meta_app)
105
105
 
@@ -158,7 +158,6 @@ class TaxonProfilesJSONBuilder(JSONBuilder):
158
158
  'metaDescription': None,
159
159
  },
160
160
  'externalMedia': [],
161
- 'templateContents': [],
162
161
  'morphotypeProfiles': [],
163
162
  'isFeatured': is_featured,
164
163
  })
@@ -433,7 +432,7 @@ class TaxonProfilesJSONBuilder(JSONBuilder):
433
432
  if vernacular_start_letter not in start_letters['vernacular'][language_code]:
434
433
  start_letters['vernacular'][language_code].append(vernacular_start_letter)
435
434
 
436
- included_taxa.append(lazy_taxon.name_uuid)
435
+ included_taxa.append(str(lazy_taxon.name_uuid))
437
436
 
438
437
  # sort the localited registries
439
438
  for language_code, localized_registry in localized_registries.items():
@@ -111,19 +111,19 @@ class TaxonSerializer:
111
111
 
112
112
  def serialize(self):
113
113
 
114
- if self.lazy_taxon.name_uuid in self.taxa_builder.cache['simple']:
115
- taxon_json = self.taxa_builder.cache['simple'][self.lazy_taxon.name_uuid]
114
+ if str(self.lazy_taxon.name_uuid) in self.taxa_builder.cache['simple']:
115
+ taxon_json = self.taxa_builder.cache['simple'][str(self.lazy_taxon.name_uuid)]
116
116
 
117
117
  else:
118
118
  taxon_json = {
119
119
  'taxonLatname' : self.lazy_taxon.taxon_latname,
120
120
  'taxonAuthor' : self.lazy_taxon.taxon_author,
121
121
  'taxonSource' : self.lazy_taxon.taxon_source,
122
- 'nameUuid' : self.lazy_taxon.name_uuid,
122
+ 'nameUuid' : str(self.lazy_taxon.name_uuid),
123
123
  'taxonNuid' : self.lazy_taxon.taxon_nuid,
124
124
  }
125
125
 
126
- self.taxa_builder.cache['simple'][self.lazy_taxon.name_uuid] = taxon_json
126
+ self.taxa_builder.cache['simple'][str(self.lazy_taxon.name_uuid)] = taxon_json
127
127
 
128
128
  taxon_json_copy = copy.deepcopy(taxon_json)
129
129
 
@@ -173,8 +173,8 @@ class TaxonSerializer:
173
173
 
174
174
  def serialize_extended(self):
175
175
 
176
- if self.lazy_taxon.name_uuid in self.taxa_builder.cache['extended']:
177
- taxon_json = self.taxa_builder.cache['extended'][self.lazy_taxon.name_uuid]
176
+ if str(self.lazy_taxon.name_uuid) in self.taxa_builder.cache['extended']:
177
+ taxon_json = self.taxa_builder.cache['extended'][str(self.lazy_taxon.name_uuid)]
178
178
 
179
179
  else:
180
180
 
@@ -201,7 +201,7 @@ class TaxonSerializer:
201
201
  taxon_json['shortProfile'] = taxon_profile.short_profile
202
202
 
203
203
 
204
- self.taxa_builder.cache['extended'][self.lazy_taxon.name_uuid] = taxon_json
204
+ self.taxa_builder.cache['extended'][str(self.lazy_taxon.name_uuid)] = taxon_json
205
205
 
206
206
  taxon_json_copy = copy.deepcopy(taxon_json)
207
207
 
@@ -222,8 +222,8 @@ class TaxonSerializer:
222
222
 
223
223
  def serialize_images(self):
224
224
 
225
- if self.lazy_taxon.name_uuid in self.taxa_builder.cache['images']:
226
- taxon_images = self.taxa_builder.cache['images'][self.lazy_taxon.name_uuid]
225
+ if str(self.lazy_taxon.name_uuid) in self.taxa_builder.cache['images']:
226
+ taxon_images = self.taxa_builder.cache['images'][str(self.lazy_taxon.name_uuid)]
227
227
 
228
228
  else:
229
229
 
@@ -314,7 +314,7 @@ class TaxonSerializer:
314
314
  collected_content_image_ids.add(taxon_image.id)
315
315
  collected_image_store_ids.add(taxon_image.image_store.id)
316
316
 
317
- self.taxa_builder.cache['images'][self.lazy_taxon.name_uuid] = taxon_images
317
+ self.taxa_builder.cache['images'][str(self.lazy_taxon.name_uuid)] = taxon_images
318
318
 
319
319
  taxon_images_copy = copy.deepcopy(taxon_images)
320
320
 
@@ -334,6 +334,9 @@ class TaxonSerializer:
334
334
  if not accepted_name_uuid:
335
335
  accepted_name_uuid = self.lazy_taxon.name_uuid
336
336
 
337
+ if accepted_name_uuid:
338
+ accepted_name_uuid = str(accepted_name_uuid)
339
+
337
340
  has_taxon_profile = False
338
341
  taxon_profile = self.get_taxon_profile()
339
342
  if taxon_profile:
@@ -358,7 +361,7 @@ class TaxonSerializer:
358
361
 
359
362
  def serialize_as_registry_taxon(self, languages, name_type, name, is_preferred_name, accepted_name_uuid=None):
360
363
 
361
- if self.lazy_taxon.name_uuid in self.taxa_builder.cache['registry']:
364
+ if str(self.lazy_taxon.name_uuid) in self.taxa_builder.cache['registry']:
362
365
  registry_taxon_json = self.taxa_builder.cache['registry']
363
366
 
364
367
  else:
@@ -376,7 +379,7 @@ class TaxonSerializer:
376
379
  if preferred_vernacular_name:
377
380
  registry_taxon_json['vernacularNames'][language_code] = preferred_vernacular_name
378
381
 
379
- self.taxa_builder.cache['registry'][self.lazy_taxon.name_uuid] = registry_taxon_json
382
+ self.taxa_builder.cache['registry'][str(self.lazy_taxon.name_uuid)] = registry_taxon_json
380
383
 
381
384
  registry_taxon_json_copy = copy.deepcopy(registry_taxon_json)
382
385
 
@@ -40,6 +40,13 @@
40
40
  </div>
41
41
  {% endfor %}
42
42
  <div>
43
+ {% if updated %}
44
+ <div class="col-12">
45
+ <div class="alert alert-success">
46
+ {% trans 'Taxon references have been updated successfully.' %}
47
+ </div>
48
+ </div>
49
+ {% endif %}
43
50
  <div class="col-12">
44
51
  <form id="update-taxa-form" method="POST" action="{% url 'update_taxon_references' meta_app.id %}">
45
52
  {% csrf_token %}
@@ -4,9 +4,14 @@ from django.core.management.base import BaseCommand, CommandError
4
4
  from django.conf import settings
5
5
  from django.contrib.contenttypes.models import ContentType
6
6
  from django_tenants.utils import schema_context # Assuming django-tenants for multi-tenancy
7
+ from django.core import serializers
8
+
9
+ from app_kit.features.nature_guides.models import (NatureGuide, MetaNode, NatureGuidesTaxonTree, NatureGuideCrosslinks, MatrixFilterSpace,
10
+ NatureGuidesTaxonSynonym, NatureGuidesTaxonLocale, MatrixFilter, NodeFilterSpace,
11
+ MatrixFilterRestriction)
12
+
13
+ from app_kit.models import ContentImage, ImageStore
7
14
 
8
- from app_kit.features.nature_guides.models import NatureGuide, MetaNode, NatureGuidesTaxonTree, MatrixFilterSpace
9
- from app_kit.models import ContentImage
10
15
 
11
16
  class Command(BaseCommand):
12
17
  help = 'Export all Nature Guides as ZIP files for a specific tenant schema'
@@ -39,7 +44,41 @@ class Command(BaseCommand):
39
44
  )
40
45
 
41
46
  # get all full filepaths of those images
42
- image_filepaths = [ci.file.path for ci in content_images if ci.file]
43
-
47
+ image_filepaths = []
48
+ for ci in content_images:
49
+ if ci.image_store and ci.image_store.source_image:
50
+ image_filepaths.append(ci.image_store.source_image.path)
51
+
52
+ # zip all those images into a single zip file
53
+ zip_filename = os.path.join(export_path, f'nature_guides_images_{schema_name}.zip')
54
+ with zipfile.ZipFile(zip_filename, 'w') as zipf:
55
+ for filepath in image_filepaths:
56
+ arcname = os.path.relpath(filepath, settings.MEDIA_ROOT)
57
+ zipf.write(filepath, arcname)
58
+
59
+ # Collect all objects to export
60
+ all_objects = []
61
+ nature_guide_models = [NatureGuide, MetaNode, NatureGuidesTaxonTree, NatureGuideCrosslinks, MatrixFilterSpace,
62
+ NatureGuidesTaxonSynonym, NatureGuidesTaxonLocale, MatrixFilter, NodeFilterSpace,
63
+ MatrixFilterRestriction]
64
+ for model in nature_guide_models:
65
+ all_objects.extend(model.objects.all())
66
+ all_objects.extend(content_images) # The filtered ContentImage instances
67
+
68
+ # Collect related ImageStore instances
69
+ image_stores = [ci.image_store for ci in content_images if ci.image_store]
70
+ all_objects.extend(image_stores)
71
+
72
+ # Serialize to JSON
73
+ data_filename = os.path.join(export_path, 'nature_guides_data.json')
74
+ with open(data_filename, 'w') as f:
75
+ serializers.serialize('json', all_objects, stream=f)
76
+
77
+ # Add the data file to the ZIP
78
+ with zipfile.ZipFile(zip_filename, 'a') as zipf:
79
+ zipf.write(data_filename, 'nature_guides_data.json')
80
+
81
+ # Optionally, remove the temporary data file after adding to ZIP
82
+ os.remove(data_filename)
44
83
 
45
84
  self.stdout.write(f'All Nature Guides exported to: {export_path}')
@@ -0,0 +1,64 @@
1
+ import os
2
+ import zipfile
3
+ import tempfile
4
+ from django.core.management.base import BaseCommand, CommandError
5
+ from django.conf import settings
6
+ from django_tenants.utils import schema_context
7
+ from django.core.management import call_command
8
+
9
+
10
+ class Command(BaseCommand):
11
+ help = 'Import all Nature Guides from a ZIP file for a specific tenant schema'
12
+
13
+ def add_arguments(self, parser):
14
+ parser.add_argument(
15
+ 'schema_name',
16
+ type=str,
17
+ help='The tenant schema name to import Nature Guides into (required).',
18
+ )
19
+ parser.add_argument(
20
+ '--zip-path',
21
+ type=str,
22
+ help='Path to the ZIP file to import (optional, defaults to the export path).',
23
+ )
24
+
25
+ def handle(self, *args, **options):
26
+ schema_name = options['schema_name']
27
+ zip_path = options.get('zip_path')
28
+
29
+ if not zip_path:
30
+ export_path = os.path.join(settings.MEDIA_ROOT, 'nature_guides_exports', schema_name)
31
+ zip_path = os.path.join(export_path, f'nature_guides_images_{schema_name}.zip')
32
+
33
+ if not os.path.exists(zip_path):
34
+ raise CommandError(f'ZIP file not found: {zip_path}')
35
+
36
+ # Use schema_context to switch to the tenant's schema
37
+ with schema_context(schema_name):
38
+ # Create a temporary directory to extract files
39
+ with tempfile.TemporaryDirectory() as temp_dir:
40
+ # Extract the ZIP file
41
+ with zipfile.ZipFile(zip_path, 'r') as zipf:
42
+ zipf.extractall(temp_dir)
43
+
44
+ # Find the data JSON file
45
+ data_filename = os.path.join(temp_dir, 'nature_guides_data.json')
46
+ if not os.path.exists(data_filename):
47
+ raise CommandError('nature_guides_data.json not found in ZIP')
48
+
49
+ # Load the data using loaddata
50
+ call_command('loaddata', data_filename, verbosity=1)
51
+
52
+ # Extract images to MEDIA_ROOT
53
+ for root, dirs, files in os.walk(temp_dir):
54
+ for file in files:
55
+ if file.endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff')): # Add more extensions if needed
56
+ src_path = os.path.join(root, file)
57
+ # Calculate the relative path from temp_dir
58
+ rel_path = os.path.relpath(src_path, temp_dir)
59
+ dest_path = os.path.join(settings.MEDIA_ROOT, rel_path)
60
+ os.makedirs(os.path.dirname(dest_path), exist_ok=True)
61
+ # Move or copy the file
62
+ os.rename(src_path, dest_path) # Use shutil.move if needed
63
+
64
+ self.stdout.write(f'All Nature Guides imported successfully for schema: {schema_name}')
@@ -22,6 +22,8 @@ from django.db import transaction
22
22
  # Python 3
23
23
  import logging, html
24
24
 
25
+ DEBUG = False
26
+
25
27
 
26
28
  '''
27
29
  base
@@ -208,7 +210,7 @@ class SourceTreeTaxon(SourceTaxon):
208
210
  def set_nuid_from_db(self):
209
211
 
210
212
  if self.nuid is None:
211
- print('setting nuid from db')
213
+ #print('setting nuid from db')
212
214
  db_entry = self.TreeModel.objects.filter(source_id=self.source_id).first()
213
215
  if db_entry:
214
216
  self.nuid = db_entry.taxon_nuid
@@ -764,7 +766,9 @@ class TaxonSourceManager:
764
766
  last_child = self._climb_down(start_taxon)
765
767
 
766
768
  message = 'last_child: {0}, nuid: {1}'.format(last_child.latname, last_child.get_nuid())
767
- print(message)
769
+
770
+ if DEBUG == True:
771
+ print(message)
768
772
  # self.logger.info(message)
769
773
 
770
774
  # search siblings of this childless taxon, or parent siblings if no siblings available
@@ -782,8 +786,10 @@ class TaxonSourceManager:
782
786
  if next_parent:
783
787
  start_taxon = next_parent
784
788
  message = 'starting nuid (next_parent): {0}'.format(start_taxon.get_nuid())
785
- print(message)
786
- # self.logger.info(message)
789
+
790
+ if DEBUG == True:
791
+ print(message)
792
+ # self.logger.info(message)
787
793
 
788
794
  else:
789
795
  continue_climbing = False
@@ -1063,8 +1069,10 @@ class TaxonSourceManager:
1063
1069
  def _climb_down(self, parent_taxon):
1064
1070
 
1065
1071
  message = 'climb down: {0}'.format(parent_taxon.latname)
1066
- print(message)
1067
- # self.logger.info(message)
1072
+
1073
+ if DEBUG == True:
1074
+ print(message)
1075
+ # self.logger.info(message)
1068
1076
 
1069
1077
  # if no nuid is found, it might be a duplicate
1070
1078
  is_duplicate = self._check_taxon_duplicate(parent_taxon)