add location migrate
This commit is contained in:
176
migrate_location_to_location2025_enhanced.py
Normal file
176
migrate_location_to_location2025_enhanced.py
Normal file
@ -0,0 +1,176 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
LocationからLocation2025への完全データ移行スクリプト(フィールド追加版)
|
||||
|
||||
更新内容:
|
||||
- photos, videos, remark, tags, evaluation_value, hidden_location フィールドを追加
|
||||
- cp_pointとphoto_pointは同じもので、checkin_pointとして移行
|
||||
- location.cpを直接location2025.cp_numberに書き込み
|
||||
"""
|
||||
|
||||
import os
|
||||
import django
|
||||
|
||||
# Django設定
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||
django.setup()
|
||||
|
||||
from rog.models import Location, Location2025, NewEvent2
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.gis.geos import Point
|
||||
from collections import defaultdict
|
||||
|
||||
def main():
|
||||
User = get_user_model()
|
||||
default_user = User.objects.first()
|
||||
|
||||
print('=== Location から Location2025 への完全データ移行(フィールド追加版) ===')
|
||||
|
||||
# 1. Location2025の既存データを削除
|
||||
print('\n1. Location2025の既存データを削除中...')
|
||||
deleted_count = Location2025.objects.count()
|
||||
Location2025.objects.all().delete()
|
||||
print(f' 削除済み: {deleted_count}件')
|
||||
|
||||
# 2. NewEvent2のevent_codeマップを作成
|
||||
print('\n2. NewEvent2のevent_codeマップを作成中...')
|
||||
events = NewEvent2.objects.filter(event_code__isnull=False).exclude(event_code='')
|
||||
event_code_map = {}
|
||||
for event in events:
|
||||
event_code_map[event.event_code] = event
|
||||
print(f' 有効なevent_code数: {len(event_code_map)}件')
|
||||
|
||||
# 3. 全Locationを取得し、cp_number+event_idのユニークな組み合わせのみを処理
|
||||
print('\n3. ユニークなcp_number+event_idの組み合わせで移行中...')
|
||||
|
||||
locations = Location.objects.all()
|
||||
processed_combinations = set()
|
||||
migrated_count = 0
|
||||
skipped_count = 0
|
||||
error_count = 0
|
||||
event_stats = defaultdict(int)
|
||||
|
||||
for location in locations:
|
||||
try:
|
||||
# groupが空の場合はスキップ
|
||||
if not location.group:
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# location.groupに含まれるevent_codeを検索
|
||||
matched_event = None
|
||||
matched_event_code = None
|
||||
|
||||
for event_code, event in event_code_map.items():
|
||||
if event_code in location.group:
|
||||
matched_event = event
|
||||
matched_event_code = event_code
|
||||
break
|
||||
|
||||
# マッチするevent_codeがない場合はスキップ
|
||||
if not matched_event:
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# cp_number + event_idの組み合わせを確認
|
||||
combination_key = (location.cp, matched_event.id)
|
||||
if combination_key in processed_combinations:
|
||||
skipped_count += 1
|
||||
continue
|
||||
|
||||
# この組み合わせを処理済みとしてマーク
|
||||
processed_combinations.add(combination_key)
|
||||
|
||||
# MultiPointからPointに変換
|
||||
point_location = None
|
||||
if location.geom and len(location.geom) > 0:
|
||||
first_point = location.geom[0]
|
||||
point_location = Point(first_point.x, first_point.y)
|
||||
elif location.longitude and location.latitude:
|
||||
point_location = Point(location.longitude, location.latitude)
|
||||
|
||||
# Location2025レコードを作成(update_or_create使用)
|
||||
location2025, created = Location2025.objects.update_or_create(
|
||||
cp_number=location.cp, # location.cpを直接使用
|
||||
event=matched_event,
|
||||
defaults={
|
||||
'cp_name': location.location_name or '',
|
||||
'sub_loc_id': location.sub_loc_id or '',
|
||||
'subcategory': location.subcategory or '',
|
||||
'latitude': location.latitude or 0.0,
|
||||
'longitude': location.longitude or 0.0,
|
||||
'location': point_location,
|
||||
# cp_pointとphoto_pointは同じもので、checkin_pointとして移行
|
||||
'cp_point': int(location.checkin_point) if location.checkin_point else 0,
|
||||
'photo_point': int(location.checkin_point) if location.checkin_point else 0,
|
||||
'buy_point': int(location.buy_point) if location.buy_point else 0,
|
||||
'checkin_radius': location.checkin_radius or 100.0,
|
||||
'auto_checkin': location.auto_checkin or False,
|
||||
'shop_closed': location.shop_closed or False,
|
||||
'shop_shutdown': location.shop_shutdown or False,
|
||||
'opening_hours': '',
|
||||
'address': location.address or '',
|
||||
'phone': location.phone or '',
|
||||
'website': '',
|
||||
'description': location.remark or '',
|
||||
# 追加フィールド
|
||||
'photos': location.photos or '',
|
||||
'videos': location.videos or '',
|
||||
'remark': location.remark or '',
|
||||
'tags': location.tags or '',
|
||||
'evaluation_value': location.evaluation_value or '',
|
||||
'hidden_location': location.hidden_location or False,
|
||||
# 管理情報
|
||||
'is_active': True,
|
||||
'sort_order': 0,
|
||||
'csv_source_file': 'migration_from_location',
|
||||
'created_by': default_user,
|
||||
'updated_by': default_user,
|
||||
}
|
||||
)
|
||||
|
||||
if created:
|
||||
migrated_count += 1
|
||||
event_stats[matched_event_code] += 1
|
||||
|
||||
if migrated_count % 100 == 0:
|
||||
print(f' 進捗: {migrated_count}件完了')
|
||||
|
||||
except Exception as e:
|
||||
print(f' ❌ エラー: CP {location.cp} - {str(e)}')
|
||||
error_count += 1
|
||||
|
||||
# 4. 結果サマリー
|
||||
print(f'\n=== 移行結果サマリー ===')
|
||||
print(f'移行完了: {migrated_count}件')
|
||||
print(f'スキップ: {skipped_count}件')
|
||||
print(f'エラー: {error_count}件')
|
||||
print(f'総処理: {migrated_count + skipped_count + error_count}件')
|
||||
|
||||
# 5. Location2025の最終件数確認
|
||||
final_count = Location2025.objects.count()
|
||||
print(f'\nLocation2025最終件数: {final_count}件')
|
||||
|
||||
# 6. event_code別の統計
|
||||
print(f'\n=== event_code別統計 ===')
|
||||
for event_code, count in event_stats.items():
|
||||
print(f' Event "{event_code}": {count}件')
|
||||
|
||||
# 7. 移行されたフィールドの確認
|
||||
if migrated_count > 0:
|
||||
print('\n=== 移行フィールド確認(サンプル) ===')
|
||||
sample = Location2025.objects.first()
|
||||
print(f' CP番号: {sample.cp_number}')
|
||||
print(f' CP名: {sample.cp_name}')
|
||||
print(f' CPポイント: {sample.cp_point}')
|
||||
print(f' フォトポイント: {sample.photo_point}')
|
||||
print(f' 写真: {sample.photos[:50]}...' if sample.photos else ' 写真: (空)')
|
||||
print(f' 動画: {sample.videos[:50]}...' if sample.videos else ' 動画: (空)')
|
||||
print(f' タグ: {sample.tags[:50]}...' if sample.tags else ' タグ: (空)')
|
||||
print(f' 評価値: {sample.evaluation_value}')
|
||||
print(f' 隠しロケーション: {sample.hidden_location}')
|
||||
|
||||
print('\n✅ 全フィールド対応のデータ移行が正常に完了しました')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user