import django.db.models.deletion from django.db import migrations, models CUISINE_SEEDS = [ ('家常菜', 0), ('本帮菜', 10), ('江浙菜', 20), ('川菜', 30), ('粤菜', 40), ('鲁菜', 50), ('湘菜', 60), ('西北菜', 70), ('面点小吃', 80), ] def seed_cuisines(apps, schema_editor): """Create Cuisine rows and save dish->cuisine mapping to a temp table.""" Cuisine = apps.get_model('meals', 'Cuisine') name_to_id = {} for name, order in CUISINE_SEEDS: obj, _ = Cuisine.objects.get_or_create(name=name, defaults={'sort_order': order}) name_to_id[name] = obj.pk from django.db import connection with connection.cursor() as cursor: cursor.execute("SELECT id, cuisine FROM meals_dish WHERE cuisine IS NOT NULL AND cuisine != ''") rows = cursor.fetchall() for _, cuisine_name in rows: if cuisine_name not in name_to_id: obj, _ = Cuisine.objects.get_or_create(name=cuisine_name, defaults={'sort_order': 90}) name_to_id[cuisine_name] = obj.pk with connection.cursor() as cursor: cursor.execute("CREATE TABLE _temp_dish_cuisine (dish_id INTEGER, cuisine_id INTEGER)") for dish_id, cuisine_name in rows: cuisine_id = name_to_id.get(cuisine_name) if cuisine_id: cursor.execute( "INSERT INTO _temp_dish_cuisine (dish_id, cuisine_id) VALUES (%s, %s)", [dish_id, cuisine_id], ) def update_cuisine_fk(apps, schema_editor): """Populate Dish.cuisine_id from the temp table, then clean up.""" from django.db import connection with connection.cursor() as cursor: cursor.execute( "UPDATE meals_dish SET cuisine_id = " "(SELECT cuisine_id FROM _temp_dish_cuisine " "WHERE _temp_dish_cuisine.dish_id = meals_dish.id) " "WHERE EXISTS (SELECT 1 FROM _temp_dish_cuisine " "WHERE _temp_dish_cuisine.dish_id = meals_dish.id)" ) cursor.execute("DROP TABLE _temp_dish_cuisine") def reverse_seed(apps, schema_editor): """Reverse: clean up temp table and delete Cuisine rows.""" from django.db import connection with connection.cursor() as cursor: cursor.execute("DROP TABLE IF EXISTS _temp_dish_cuisine") Cuisine = apps.get_model('meals', 'Cuisine') Cuisine.objects.all().delete() class Migration(migrations.Migration): """Step 2: Seed cuisines from existing data, then alter Dish.cuisine to FK.""" dependencies = [ ('meals', '0006_cuisine_dish_cuisine_fk'), ] operations = [ migrations.RunPython(seed_cuisines, reverse_seed), migrations.AlterField( model_name='dish', name='cuisine', field=models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dishes', to='meals.cuisine', verbose_name='菜系', ), ), migrations.RunPython(update_cuisine_fk, migrations.RunPython.noop), ]