diff --git a/diets/views.py b/diets/views.py index 8632134..aa35322 100644 --- a/diets/views.py +++ b/diets/views.py @@ -54,7 +54,7 @@ def food_to_dict(food): "trans_fatty_acids": safe_float(getattr(food, "trans_fatty_acids", 0)), "serving_size": safe_float(getattr(food, "serving_size", 0)), "weight": safe_float(getattr(food, "weight", 0)), - "company_name": safe_str(getattr(food, "mallName", "") or getattr(food, "company_name", "") or ""), + "company_name": safe_str(getattr(food, "company_name", "") or ""), "score": safe_float(getattr(food, "nutrition_score", 0)), "letter_grade": safe_str(getattr(food, "nutri_score_grade", "") or letterGrade(food) or ""), "nutri_score_grade": safe_str(getattr(food, "nutri_score_grade", "") or letterGrade(food) or "") @@ -181,7 +181,7 @@ def diet_list(request): recent_foods.append({ "food_id": str(cur_food.food_id), "food_name" : cur_food.food_name, - "company_name": cur_food.mallName or cur_food.company_name, + "company_name": cur_food.company_name, "food_img": cur_food.image_url or cur_food.food_img }) cnt += 1 #식품 카운팅 @@ -212,7 +212,7 @@ def diet_search(request): food_data = dict() #food의 정보를 담을 dict food_data['food_id'] = str(food.food_id) food_data['food_name'] = food.food_name - food_data['company_name'] = food.mallName or food.company_name + food_data['company_name'] = food.company_name food_data['food_img'] = food.image_url or food.food_img ret['foods'].append(food_data) #food_data 에 정보를 모두 담았으니 ret['foods']에 추가 diff --git a/foods/admin.py b/foods/admin.py index 7ed674e..d39f898 100644 --- a/foods/admin.py +++ b/foods/admin.py @@ -4,8 +4,8 @@ @admin.register(Food) class FoodAdmin(admin.ModelAdmin): - list_display = ['food_id', 'food_name', 'company_name', 'food_category', 'mallName', 'lprice'] - list_filter = ['food_category', 'company_name', 'mallName'] + list_display = ['food_id', 'food_name', 'company_name', 'food_category', 'lprice'] + list_filter = ['food_category', 'company_name'] search_fields = ['food_name', 'company_name', 'representative_food'] readonly_fields = ['food_id'] @@ -29,7 +29,7 @@ class FoodAdmin(admin.ModelAdmin): 'classes': ('collapse',) }), ('가격 정보', { - 'fields': ('mallName', 'lprice', 'discount_price', 'shop_url', 'image_url'), + 'fields': ('lprice', 'discount_price', 'shop_url', 'image_url'), 'classes': ('collapse',) }), ('기타 정보', { diff --git a/foods/migrations/0011_remove_food_mallname.py b/foods/migrations/0011_remove_food_mallname.py new file mode 100644 index 0000000..1fc2122 --- /dev/null +++ b/foods/migrations/0011_remove_food_mallname.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.4 on 2025-08-18 10:38 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('foods', '0010_remove_food_shop_name'), + ] + + operations = [ + migrations.RemoveField( + model_name='food', + name='mallName', + ), + ] diff --git a/foods/models.py b/foods/models.py index f748cc0..30af98f 100644 --- a/foods/models.py +++ b/foods/models.py @@ -53,7 +53,6 @@ class Food(models.Model): # 가격 정보 (CSV 칼럼에 맞춰 추가) lprice = models.BigIntegerField(null=True, blank=True) # 네이버 쇼핑 최저가 discount_price = models.BigIntegerField(null=True, blank=True) - mallName = models.CharField(max_length=100, null=True, blank=True) # 쇼핑몰 이름 shop_url = models.URLField(null=True, blank=True) image_url = models.URLField(null=True, blank=True) diff --git a/mypage/views.py b/mypage/views.py index 731940a..082284f 100644 --- a/mypage/views.py +++ b/mypage/views.py @@ -114,7 +114,7 @@ def favorite_food_list(request): "food_id": str(food.food_id), "food_name": food.food_name, "food_img": getattr(food, 'image_url', '') or getattr(food, 'food_img', '') or "http://example.com/default_food.png", - "company_name": getattr(food, 'mallName', '') or getattr(food, 'company_name', '') or "Unknown", + "company_name": getattr(food, 'company_name', '') or "Unknown", "calorie": int(food.calorie) if getattr(food, 'calorie', None) else 0, "created_at": getattr(f, 'created_at', None), }) diff --git a/products/views.py b/products/views.py index 0bc35ab..54150ef 100644 --- a/products/views.py +++ b/products/views.py @@ -73,11 +73,10 @@ def _product_dict(food, is_favorite: bool): "trans_fatty_acids": safe_float(food.trans_fatty_acids), "nutritional_value_standard_amount": safe_int(food.nutritional_value_standard_amount), "weight": safe_float(food.weight), - "company_name": safe_str(food.mallName) or safe_str(food.company_name), + "company_name": safe_str(food.company_name), "nutrition_score": safe_float(food.nutrition_score), "nutri_score_grade": safe_str(food.nutri_score_grade), "lprice": safe_int(food.lprice), - "shop_name": safe_str(food.mallName), "shop_url": safe_str(food.shop_url), "sugar_level": None, "saturated_fatty_acids_level": None, diff --git a/scripts/extract_manufacturer_info.py b/scripts/extract_manufacturer_info.py new file mode 100644 index 0000000..a2b0411 --- /dev/null +++ b/scripts/extract_manufacturer_info.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +""" +20250327_가공식품DB_147999건.xlsx에서 제조사 정보를 추출하여 +food_clean_data.csv의 company_name을 업데이트하는 스크립트 +""" + +import pandas as pd + +def main(): + print("제조사 정보 추출 및 매핑 시작...") + + try: + # 1. 원본 Excel 파일 읽기 + print("20250327_가공식품DB_147999건.xlsx 로딩 중...") + df_original = pd.read_excel('/Users/kimminji/Desktop/Healthtant/20250327_가공식품DB_147999건.xlsx') + print(f"원본 데이터: {len(df_original)}개 행") + + # 2. food_clean_data.csv 읽기 + print("food_clean_data.csv 로딩 중...") + df_food = pd.read_csv('/Users/kimminji/Desktop/Healthtant/food_clean_data.csv') + print(f"현재 식품 데이터: {len(df_food)}개 행") + + # 3. 제조사 정보 추출 (식품코드 -> 제조사명) + manufacturer_mapping = {} + for idx, row in df_original.iterrows(): + food_code = str(row['식품코드']).strip() + manufacturer = str(row['제조사명']).strip() if pd.notna(row['제조사명']) else '' + + # 제조사명이 없으면 수입업체명이나 유통업체명 사용 + if not manufacturer or manufacturer == 'nan': + manufacturer = str(row['수입업체명']).strip() if pd.notna(row['수입업체명']) else '' + if not manufacturer or manufacturer == 'nan': + manufacturer = str(row['유통업체명']).strip() if pd.notna(row['유통업체명']) else '' + + if manufacturer and manufacturer != 'nan': + manufacturer_mapping[food_code] = manufacturer + + print(f"제조사 정보를 찾은 식품: {len(manufacturer_mapping)}개") + + # 4. food_clean_data.csv의 company_name 업데이트 + updated_count = 0 + for idx, row in df_food.iterrows(): + food_id = str(row['food_id']).strip() + if food_id in manufacturer_mapping: + df_food.at[idx, 'company_name'] = manufacturer_mapping[food_id] + updated_count += 1 + + print(f"업데이트된 식품: {updated_count}개") + + # 5. 업데이트된 CSV 저장 + output_file = '/Users/kimminji/Desktop/Healthtant/food_clean_data_updated.csv' + df_food.to_csv(output_file, index=False, encoding='utf-8') + print(f"업데이트된 파일 저장: {output_file}") + + # 6. 통계 출력 + total_foods = len(df_food) + foods_with_manufacturer = len(df_food[df_food['company_name'].notna() & (df_food['company_name'] != '') & (df_food['company_name'] != 'UNKNOWN')]) + print(f"\n=== 통계 ===") + print(f"전체 식품: {total_foods}개") + print(f"제조사 정보 있음: {foods_with_manufacturer}개 ({foods_with_manufacturer/total_foods*100:.1f}%)") + + # 7. 샘플 데이터 확인 + print(f"\n=== 업데이트된 샘플 데이터 ===") + sample = df_food[df_food['company_name'].notna() & (df_food['company_name'] != '') & (df_food['company_name'] != 'UNKNOWN')].head(10) + for _, row in sample.iterrows(): + print(f"ID: {row['food_id']}, 식품명: {row['food_name']}, 제조사: {row['company_name']}") + + except Exception as e: + print(f"오류 발생: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/scripts/extract_manufacturers.py b/scripts/extract_manufacturers.py deleted file mode 100644 index 815469d..0000000 --- a/scripts/extract_manufacturers.py +++ /dev/null @@ -1,69 +0,0 @@ -import pandas as pd -import os - -def extract_manufacturers(): - """가공식품DB에서 제조사 정보 추출하여 현재 food_id와 매칭""" - - # 1. 가공식품DB 로드 - excel_file = '20250327_가공식품DB_147999건.xlsx' - if not os.path.exists(excel_file): - print(f"ERROR: {excel_file} 파일이 없습니다.") - return - - print("가공식품DB 로딩 중...") - df_full = pd.read_excel(excel_file, dtype=str) - print(f"전체 가공식품DB: {len(df_full)}개 행") - print(f"컬럼: {list(df_full.columns)}") - - # 2. 현재 food_clean_mallname.csv 로드 - current_file = 'food_clean_mallname.csv' - if not os.path.exists(current_file): - print(f"ERROR: {current_file} 파일이 없습니다.") - return - - df_current = pd.read_csv(current_file, dtype=str) - print(f"현재 데이터: {len(df_current)}개 행") - current_food_ids = set(df_current['food_id'].tolist()) - - # 3. food_id로 매칭하여 제조사 정보 추출 - print("\n=== 제조사 정보 매칭 중 ===") - - # 매칭 결과를 저장할 리스트 - manufacturer_mappings = [] - matched_count = 0 - - for _, current_row in df_current.iterrows(): - food_id = current_row['food_id'] - - # 가공식품DB에서 해당 식품코드 찾기 - matching_rows = df_full[df_full['식품코드'] == food_id] - - if len(matching_rows) > 0: - manufacturer = matching_rows.iloc[0]['제조사명'] - if pd.notna(manufacturer) and str(manufacturer).strip() != '': - manufacturer_mappings.append({ - 'food_id': food_id, - 'food_name': current_row['food_name'], - 'manufacturer_name': str(manufacturer).strip() - }) - matched_count += 1 - - print(f"매칭된 제품: {matched_count}개 / {len(df_current)}개") - - # 4. 매칭 결과를 CSV로 저장 - if manufacturer_mappings: - df_manufacturers = pd.DataFrame(manufacturer_mappings) - output_file = 'manufacturer_mappings.csv' - df_manufacturers.to_csv(output_file, index=False, encoding='utf-8') - print(f"\n제조사 매핑 파일 생성: {output_file}") - print(f"총 {len(df_manufacturers)}개 제품의 제조사 정보 추출 완료") - - # 샘플 출력 - print("\n=== 제조사 매핑 샘플 ===") - for _, row in df_manufacturers.head(10).iterrows(): - print(f"{row['food_id']}: {row['food_name']} → {row['manufacturer_name']}") - else: - print("매칭된 제조사 정보가 없습니다.") - -if __name__ == "__main__": - extract_manufacturers() \ No newline at end of file diff --git a/scripts/health_check.py b/scripts/health_check.py deleted file mode 100755 index 24d0b24..0000000 --- a/scripts/health_check.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -""" -빠른 헬스체크를 위한 스크립트 -""" -import os -import sys -import django -from pathlib import Path - -# Django 설정 -BASE_DIR = Path(__file__).resolve().parent.parent -sys.path.append(str(BASE_DIR)) -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.production') -django.setup() - -def health_check(): - """간단한 헬스체크 수행""" - try: - # 1. Database 연결 확인 - from django.db import connection - with connection.cursor() as cursor: - cursor.execute("SELECT 1") - print("✅ Database: OK") - - # 2. Django 설정 확인 - from django.conf import settings - print(f"✅ Django: OK (DEBUG={settings.DEBUG})") - - # 3. 필수 환경변수 확인 - required_env = ['POSTGRES_DB', 'POSTGRES_USER', 'POSTGRES_PASSWORD'] - for env_var in required_env: - if not os.getenv(env_var): - print(f"⚠️ Missing env var: {env_var}") - - return True - - except Exception as e: - print(f"❌ Health check failed: {e}") - return False - -if __name__ == "__main__": - success = health_check() - sys.exit(0 if success else 1) \ No newline at end of file diff --git a/scripts/insert_food_postgresql.py b/scripts/insert_food_postgresql.py index cbf4e03..c49244a 100644 --- a/scripts/insert_food_postgresql.py +++ b/scripts/insert_food_postgresql.py @@ -148,7 +148,6 @@ def main(): # 2) 매핑 - food_clean_data.csv 칼럼에 맞춰 수정 csv_to_db = { 'food_id': 'food_id', - 'shop_name': 'mallName', 'price': 'lprice', 'discount_price': 'discount_price', 'shop_url': 'shop_url', diff --git a/scripts/rebuild_clean_database.py b/scripts/rebuild_clean_database.py index e20cc6a..3c5c9b7 100644 --- a/scripts/rebuild_clean_database.py +++ b/scripts/rebuild_clean_database.py @@ -181,7 +181,6 @@ def validate_and_clean_row(args): 'food_category': (row.get('food_category', ''), 255), 'representative_food': (row.get('representative_food', ''), 255), 'company_name': (row.get('company_name', ''), 255), - 'shop_name': (row.get('mallName', ''), 100), 'nutri_score_grade': (row.get('nutri_score_grade', ''), 10), } @@ -419,7 +418,7 @@ def update_progress(): 'potassium','salt','"VitaminA"','"VitaminB"','"VitaminC"','"VitaminD"','"VitaminE"', 'cholesterol','saturated_fatty_acids','trans_fatty_acids','serving_size', 'weight','company_name','nutrition_score','nutri_score_grade','nrf_index', - 'shop_name','lprice','discount_price','shop_url','image_url' + 'lprice','discount_price','shop_url','image_url' ] placeholders = ",".join(["%s"] * len(cols)) diff --git a/scripts/update_mallname.py b/scripts/update_mallname.py deleted file mode 100644 index 63c07cc..0000000 --- a/scripts/update_mallname.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 -""" -manufacturer_mappings.csv의 제조사명을 mallName 필드에 업데이트하는 스크립트 -배포 서버에서 실행: python update_mallname.py -""" - -import os -import sys -import django -import csv - -# Django 설정 -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.base') -django.setup() - -from foods.models import Food - -def main(): - csv_path = 'manufacturer_mappings.csv' - - if not os.path.exists(csv_path): - print(f"파일을 찾을 수 없습니다: {csv_path}") - return - - updated = 0 - not_found = 0 - - print("manufacturer_mappings.csv에서 제조사명을 mallName으로 업데이트 중...") - - with open(csv_path, 'r', encoding='utf-8') as f: - reader = csv.DictReader(f) - - for row in reader: - food_id = row['food_id'] - manufacturer = row['제조사명'] - - try: - food = Food.objects.get(food_id=food_id) - food.mallName = manufacturer - food.save(update_fields=['mallName']) - updated += 1 - - if updated <= 5: - print(f'업데이트: {food_id} → {manufacturer}') - - except Food.DoesNotExist: - not_found += 1 - - print(f'\n완료!') - print(f'업데이트된 레코드: {updated}개') - print(f'찾을 수 없는 레코드: {not_found}개') - - # 결과 확인 - total_mallname = Food.objects.filter(mallName__isnull=False).exclude(mallName='').count() - print(f'전체 mallName이 있는 레코드: {total_mallname}개') - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/search/views.py b/search/views.py index 742286a..3168dab 100644 --- a/search/views.py +++ b/search/views.py @@ -89,7 +89,7 @@ def food_to_dict(food, user=None, favorite_ids=None): "trans_fatty_acids": safe_float(getattr(food, "trans_fatty_acids", 0)), "serving_size": safe_float(getattr(food, "serving_size", 0)), "weight": safe_float(getattr(food, "weight", 0)), - "company_name": safe_str(getattr(food, "mallName", "") or getattr(food, "company_name", "") or ""), + "company_name": safe_str(getattr(food, "company_name", "") or ""), "score": safe_float(getattr(food, "nutrition_score", 0)), "letter_grade": safe_str(getattr(food, "nutri_score_grade", "") or letterGrade(food) or ""), "nutri_score_grade": safe_str(getattr(food, "nutri_score_grade", "") or letterGrade(food) or ""), diff --git a/static/diets/js/diets_search.js b/static/diets/js/diets_search.js index 313b69d..0503c1e 100644 --- a/static/diets/js/diets_search.js +++ b/static/diets/js/diets_search.js @@ -124,7 +124,7 @@ function createFoodElement(food) {

${food.food_name}

-

판매처: ${food.company_name || '판매처 정보 없음'}

+

제조사: ${food.company_name || '제조사 정보 없음'}

식사로 등록하기 - {% comment %} {% if product.shop_url %} - {{ product.shop_name|default:"구매하기" }} - {% endif %} {% endcomment %} diff --git a/templates/search/advanced_search_page.html b/templates/search/advanced_search_page.html index 3c47843..4aba2d9 100644 --- a/templates/search/advanced_search_page.html +++ b/templates/search/advanced_search_page.html @@ -71,7 +71,7 @@

이 제품을 {{user.username}}님께 추천합

{{ food.food_name }}

-

판매처: {{ food.company_name|default:'판매처 정보 없음' }}

+

제조사: {{ food.company_name|default:'제조사 정보 없음' }}