@@ -24,6 +24,25 @@ def norm(s: str) -> str:
2424 s = s or ""
2525 return re .sub (r"[\s\(\)\[\]\-_/·•~!@#$%^&*=+|:;\"'<>?,.]+" , "" , s ).lower ()
2626
27+ _num_re = re .compile (r'^[\+\-]?\d+(\.\d+)?$' )
28+
29+
30+ def to_bool (v ) -> bool :
31+ if v is None :
32+ return False
33+ # 숫자형은 그대로 판단
34+ if isinstance (v , (int , float )):
35+ return float (v ) != 0.0
36+ # 문자열/그 외 → 정규화
37+ s = str (v ).strip ().lower ()
38+ # 숫자 문자열(정수/소수) 처리: "1", "1.0", "0.0", "+2", "-0.0" 등
39+ if _num_re .match (s ):
40+ try :
41+ return float (s ) != 0.0
42+ except Exception :
43+ return False
44+ # 그 외 truthy 토큰
45+ return s in {"1" , "true" , "t" , "y" , "yes" , "on" }
2746
2847class Command (BaseCommand ):
2948 help = "CSV(필수) + (선택) FAISS index에서 Place 및 임베딩을 DB에 적재 (진행률/ETA/막대 표시)."
@@ -144,7 +163,8 @@ def handle(self, *args, **opts):
144163 lng = row .get ("경도" ) or row .get ("lng" )
145164 summary = row .get ("summary" , "" )
146165 external_id = row .get ("external_id" , None )
147- is_unique = str (row .get ("is_unique" , "0" )).strip () in ["1" , "True" , "true" ]
166+ is_unique_raw = row .get ("is_unique" ) or row .get ("unique" ) or row .get ("isunique" ) or 0
167+ is_unique = to_bool (is_unique_raw )
148168 raw_cls = row .get ("class" , "0" )
149169
150170 # 필수 필드 검증
@@ -201,6 +221,11 @@ def handle(self, *args, **opts):
201221 address = address ,
202222 defaults = defaults ,
203223 )
224+ db_val = Place .objects .filter (pk = place .pk ).values_list ("is_unique" , flat = True ).first ()
225+ if db_val != is_unique :
226+ self .stderr .write (self .style .WARNING (
227+ f"[is_unique MISMATCH] name={ name } addr={ address } parsed={ is_unique } db={ db_val } "
228+ ))
204229 created += int (was_created )
205230 updated += int (not was_created )
206231
0 commit comments