1- import logging
21from typing import Dict , List , Optional
32
43from django .conf import settings
98from backend .consultations .models import CandidateTheme , Consultation , Question
109from backend .data_pipeline .models import CandidateThemeBatch , ThemeNodeList
1110
12- logger = logging . getLogger ( __name__ )
11+ logger = settings . LOGGER
1312
1413
1514# ============================================================================
@@ -46,21 +45,23 @@ def load_candidate_themes_from_s3(
4645 # Build S3 key for clustered_themes.json
4746 key = f"app_data/consultations/{ consultation_code } /outputs/sign_off/{ timestamp } /question_part_{ question_number } /clustered_themes.json"
4847
49- logger .info (f "Loading candidate themes from { key } " )
48+ logger .info ("Loading candidate themes from {key}" , key = key )
5049
5150 # Read and parse JSON file
5251 theme_data = s3 .read_json (
5352 bucket_name = bucket_name_str , key = key , s3_client = s3_client , raise_if_missing = False
5453 )
5554
5655 if theme_data is None :
57- logger .info (f "No candidate themes file found at { key } " )
56+ logger .info ("No candidate themes file found at {key}" , key = key )
5857 return []
5958
6059 validated_themes = ThemeNodeList .model_validate (theme_data ).theme_nodes
6160
6261 logger .info (
63- f"Loaded and validated { len (validated_themes )} candidate themes for question { question_number } "
62+ "Loaded and validated {theme_count} candidate themes for question {question_number}" ,
63+ theme_count = len (validated_themes ),
64+ question_number = question_number ,
6465 )
6566
6667 return validated_themes
@@ -106,8 +107,10 @@ def load_candidate_themes_batch(
106107 )
107108
108109 logger .info (
109- f"Loading candidate themes for consultation '{ consultation_code } ' "
110- f"(timestamp: { timestamp } ) across { len (question_numbers )} questions"
110+ "Loading candidate themes for consultation '{consultation_code}' (timestamp: {timestamp}) across {question_count} questions" ,
111+ consultation_code = consultation_code ,
112+ timestamp = timestamp ,
113+ question_count = len (question_numbers ),
111114 )
112115
113116 # Load themes for each question
@@ -133,7 +136,9 @@ def load_candidate_themes_batch(
133136
134137 total_themes = sum (len (themes ) for themes in themes_by_question .values ())
135138 logger .info (
136- f"Loaded { total_themes } total candidate themes across { len (themes_by_question )} questions"
139+ "Loaded {total_themes} total candidate themes across {question_count} questions" ,
140+ total_themes = total_themes ,
141+ question_count = len (themes_by_question ),
137142 )
138143
139144 return batch
@@ -159,18 +164,27 @@ def _import_candidate_themes_for_question(question: Question, themes: List[Theme
159164 themes: List of validated ThemeNode objects
160165 """
161166 if not themes :
162- logger .info (f"No candidate themes to import for question { question .number } " )
167+ logger .info (
168+ "No candidate themes to import for question {question_number}" ,
169+ question_number = question .number ,
170+ )
163171 return
164172
165173 # Delete existing candidate themes for this question (idempotent)
166174 existing_count = CandidateTheme .objects .filter (question = question ).count ()
167175 if existing_count > 0 :
168176 logger .info (
169- f"Deleting { existing_count } existing candidate themes for question { question .number } "
177+ "Deleting {existing_count} existing candidate themes for question {question_number}" ,
178+ existing_count = existing_count ,
179+ question_number = question .number ,
170180 )
171181 CandidateTheme .objects .filter (question = question ).delete ()
172182
173- logger .info (f"Importing { len (themes )} candidate themes for question { question .number } " )
183+ logger .info (
184+ "Importing {theme_count} candidate themes for question {question_number}" ,
185+ theme_count = len (themes ),
186+ question_number = question .number ,
187+ )
174188
175189 # First pass: create all themes without parent relationships
176190 themes_to_create = [
@@ -209,15 +223,24 @@ def _import_candidate_themes_for_question(question: Question, themes: List[Theme
209223 themes_to_update .append (candidate_theme )
210224 else :
211225 logger .warning (
212- f"Parent theme with topic_id '{ parent_id } ' not found for theme '{ candidate_theme .name } '"
226+ "Parent theme with topic_id '{parent_id}' not found for theme '{theme_name}'" ,
227+ parent_id = parent_id ,
228+ theme_name = candidate_theme .name ,
213229 )
214230
215231 # Bulk update parent relationships
216232 if themes_to_update :
217233 CandidateTheme .objects .bulk_update (themes_to_update , ["parent" ])
218- logger .info (f"Set { len (themes_to_update )} parent relationships" )
234+ logger .info (
235+ "Set {relationship_count} parent relationships" ,
236+ relationship_count = len (themes_to_update ),
237+ )
219238
220- logger .info (f"Created { len (created_themes )} candidate themes for question { question .number } " )
239+ logger .info (
240+ "Created {theme_count} candidate themes for question {question_number}" ,
241+ theme_count = len (created_themes ),
242+ question_number = question .number ,
243+ )
221244
222245
223246@transaction .atomic
@@ -247,12 +270,17 @@ def import_candidate_themes(batch: CandidateThemeBatch) -> None:
247270 "Base consultation data must be imported before candidate themes."
248271 )
249272
250- logger .info (f"Starting candidate themes import for consultation '{ consultation .title } '" )
273+ logger .info (
274+ "Starting candidate themes import for consultation '{consultation_title}'" ,
275+ consultation_title = consultation .title ,
276+ )
251277
252278 # Update consultation timestamp
253279 if consultation .timestamp != batch .timestamp :
254280 logger .info (
255- f"Updating consultation timestamp from '{ consultation .timestamp } ' to '{ batch .timestamp } '"
281+ "Updating consultation timestamp from '{old_timestamp}' to '{new_timestamp}'" ,
282+ old_timestamp = consultation .timestamp ,
283+ new_timestamp = batch .timestamp ,
256284 )
257285 consultation .timestamp = batch .timestamp
258286 consultation .save (update_fields = ["timestamp" ])
@@ -278,8 +306,9 @@ def import_candidate_themes(batch: CandidateThemeBatch) -> None:
278306 total_themes_created += len (themes )
279307
280308 logger .info (
281- f"Candidate themes import complete: "
282- f"{ total_themes_created } themes across { questions_imported } questions"
309+ "Candidate themes import complete: {total_themes_created} themes across {questions_imported} questions" ,
310+ total_themes_created = total_themes_created ,
311+ questions_imported = questions_imported ,
283312 )
284313
285314
@@ -311,8 +340,9 @@ def import_candidate_themes_from_s3(
311340 ValueError: If consultation or questions don't exist
312341 """
313342 logger .info (
314- f"Starting candidate themes import for consultation '{ consultation_code } ' "
315- f"(timestamp: { timestamp } )"
343+ "Starting candidate themes import for consultation '{consultation_code}' (timestamp: {timestamp})" ,
344+ consultation_code = consultation_code ,
345+ timestamp = timestamp ,
316346 )
317347
318348 # Load from S3
@@ -325,4 +355,7 @@ def import_candidate_themes_from_s3(
325355 # Import into database
326356 import_candidate_themes (batch )
327357
328- logger .info (f"Candidate themes import complete for consultation '{ consultation_code } '" )
358+ logger .info (
359+ "Candidate themes import complete for consultation '{consultation_code}'" ,
360+ consultation_code = consultation_code ,
361+ )
0 commit comments