Files
app-store-optimization/skills/loki-mode/benchmarks/results/2026-01-05-10-37-54/swebench-loki-patches/django__django-11910.patch

100 lines
5.8 KiB
Diff

# django__django-11910
# Loki Mode Multi-Agent Patch
# Attempts: 1
Based on the issue description and the architect's analysis, I need to generate a patch for the Django migration autodetector. The bug is that when renaming a PrimaryKey field, the autodetector generates an unnecessary `AlterField` operation for ForeignKey fields that reference the old field name in `to_field`.
Here's the patch:
```
--- a/django/db/migrations/autodetector.py
+++ b/django/db/migrations/autodetector.py
@@ -1003,6 +1003,21 @@ class MigrationAutodetector:
)
)
+ def _get_altered_pk_to_field_name(self, app_label, model_name, old_field_name):
+ """
+ Return the new field name if the field was renamed, None otherwise.
+ """
+ for rename_app, rename_model, old_name, new_name in self.renamed_fields:
+ if (rename_app, rename_model, old_name) == (app_label, model_name, old_field_name):
+ return new_name
+ return None
+
+ def _field_was_renamed(self, app_label, model_name, old_name):
+ """Check if a field was renamed."""
+ for rename_app, rename_model, rename_old, rename_new in self.renamed_fields:
+ if (rename_app, rename_model, rename_old) == (app_label, model_name, old_name):
+ return True
+ return False
+
def generate_altered_fields(self):
"""
Make AlterField operations, or possibly RemovedField/AddField if alter
@@ -1028,6 +1043,26 @@ class MigrationAutodetector:
old_field_dec = self.deep_deconstruct(old_field)
new_field_dec = self.deep_deconstruct(new_field)
if old_field_dec != new_field_dec:
+ # Check if this is a ForeignKey/OneToOneField where the only
+ # difference is the to_field pointing to a renamed field
+ if (
+ hasattr(old_field, 'remote_field') and
+ old_field.remote_field and
+ hasattr(new_field, 'remote_field') and
+ new_field.remote_field
+ ):
+ old_to_field = old_field_dec[2].get('to_field')
+ new_to_field = new_field_dec[2].get('to_field')
+ if old_to_field and new_to_field is None:
+ # Check if the old to_field was renamed
+ related_model = old_field.remote_field.model
+ if hasattr(related_model, '_meta'):
+ related_app = related_model._meta.app_label
+ related_model_name = related_model._meta.model_name
+ if self._field_was_renamed(related_app, related_model_name, old_to_field):
+ # Skip this AlterField as the RenameField handles it
+ continue
+
both_m2m = old_field.many_to_many and new_field.many_to_many
neither_m2m = not old_field.many_to_many and not new_field.many_to_many
if both_m2m or neither_m2m:
```
Wait, let me reconsider the issue more carefully. The problem is that after renaming a PrimaryKey field, the migration autodetector generates an `AlterField` for ForeignKey fields with the old `to_field` value. The real fix should be in how the autodetector compares the old and new field definitions when a referenced field has been renamed.
Let me provide a corrected patch:
--- a/django/db/migrations/autodetector.py
+++ b/django/db/migrations/autodetector.py
@@ -1028,6 +1028,30 @@ class MigrationAutodetector:
old_field_dec = self.deep_deconstruct(old_field)
new_field_dec = self.deep_deconstruct(new_field)
if old_field_dec != new_field_dec:
+ # Check if this is a ForeignKey/OneToOneField where the only
+ # difference is the to_field pointing to a field that was renamed.
+ # In such cases, RenameField already handles the database changes.
+ if (
+ hasattr(old_field, 'remote_field') and
+ old_field.remote_field and
+ hasattr(new_field, 'remote_field') and
+ new_field.remote_field
+ ):
+ old_to_field = old_field_dec[2].get('to_field')
+ new_to_field = new_field_dec[2].get('to_field')
+ if old_to_field and old_to_field != new_to_field:
+ # Check if the old to_field was renamed to the new to_field
+ remote_model_name = old_field.remote_field.model._meta.model_name
+ remote_app_label = old_field.remote_field.model._meta.app_label
+ for renamed_app, renamed_model, old_name, new_name in self.renamed_fields:
+ if (
+ renamed_app == remote_app_label and
+ renamed_model == remote_model_name and
+ old_name == old_to_field and
+ (new_name == new_to_field or new_to_field is None)
+ ):
+ continue
+
both_m2m = old_field.many_to_many and new_field.many_to_many
neither_m2m = not old_field.many_to_many and not new_field.many_to_many
if both_m2m or neither_m2m: