adamchainz / django-upgrade

Automatically upgrade your Django projects.
MIT License
975 stars 62 forks source link

Add Model.Meta.index_together fixer #464

Closed adamchainz closed 2 months ago

adamchainz commented 2 months ago

Fixes #344.

Handles both forms of index_together, in list and tuple, and with/without existing indexes definition. Tried to cover every edge case I could think of, per tests.

Tested on Sentry, the only project I could find with historical index_together definitions. Use this commit: https://github.com/getsentry/sentry/commit/a32270c8ab84d341d97e15e95e0fa6832ae0a17c, just before github.com/getsentry/sentry/commit/00884d133eaaedf3e69bc8ab3d3bca781e0c425f and later commits updated index_together.

Saw successful rewrites:

$ git ls-files -z '*.py' | xargs -0 django-upgrade --target-version 4.2 --only index_together
Rewriting src/sentry/feedback/models.py
Rewriting src/sentry/incidents/models.py
Rewriting src/sentry/models/activity.py
Rewriting src/sentry/models/artifactbundle.py
Rewriting src/sentry/models/commit.py
Rewriting src/sentry/models/debugfile.py
Rewriting src/sentry/models/eventattachment.py
Rewriting src/sentry/models/group.py
Rewriting src/sentry/models/grouphistory.py
Rewriting src/sentry/models/groupinbox.py
Rewriting src/sentry/models/grouprelease.py
Rewriting src/sentry/models/organizationmembermapping.py
Rewriting src/sentry/models/outbox.py
Rewriting src/sentry/models/pullrequest.py
Rewriting src/sentry/models/release.py
Rewriting src/sentry/models/releasefile.py
Rewriting src/sentry/models/releaseprojectenvironment.py
Rewriting src/sentry/models/rule.py
Rewriting src/sentry/models/statistical_detectors.py
Rewriting src/sentry/models/userreport.py
Rewriting src/sentry/replays/models.py

...and the diff looks good:

$ git diff '*.py' | head -n 50
diff --git src/sentry/feedback/models.py src/sentry/feedback/models.py
index 3527d584bc4..b15d3a8ba45 100644
--- src/sentry/feedback/models.py
+++ src/sentry/feedback/models.py
@@ -27,6 +27,6 @@ class Feedback(Model):
     class Meta:
         app_label = "feedback"
         db_table = "feedback_feedback"
-        index_together = [("project_id", "date_added")]
+        indexes = [models.Index(fields=("project_id", "date_added"))]

     __repr__ = sane_repr("project_id", "feedback_id")
diff --git src/sentry/incidents/models.py src/sentry/incidents/models.py
index 6a4f4f6ae39..06e84dc7136 100644
--- src/sentry/incidents/models.py
+++ src/sentry/incidents/models.py
@@ -205,7 +205,7 @@ class Meta:
         app_label = "sentry"
         db_table = "sentry_incident"
         unique_together = (("organization", "identifier"),)
-        index_together = (("alert_rule", "type", "status"),)
+        indexes = [models.Index(fields=("alert_rule", "type", "status"))]

     @property
     def current_end_date(self):
@@ -561,7 +561,7 @@ class Meta:
         app_label = "sentry"
         db_table = "sentry_incidenttrigger"
         unique_together = (("incident", "alert_rule_trigger"),)
-        index_together = (("alert_rule_trigger", "incident_id"),)
+        indexes = [models.Index(fields=("alert_rule_trigger", "incident_id"))]

 class AlertRuleTriggerManager(BaseManager["AlertRuleTrigger"]):
diff --git src/sentry/models/activity.py src/sentry/models/activity.py
index aa9e0545adc..57575e9ac6b 100644
--- src/sentry/models/activity.py
+++ src/sentry/models/activity.py
@@ -109,7 +109,7 @@ class Activity(Model):
     class Meta:
         app_label = "sentry"
         db_table = "sentry_activity"
-        index_together = (("project", "datetime"),)
+        indexes = [models.Index(fields=("project", "datetime"))]

     __repr__ = sane_repr("project_id", "group_id", "event_id", "user_id", "type", "ident")

diff --git src/sentry/models/artifactbundle.py src/sentry/models/artifactbundle.py
index 323912d6d98..cbfb61c8805 100644
--- src/sentry/models/artifactbundle.py

One model was missed due to no from django.db import models in the file - I am gonna leave that for extension, if anyone wants.

adamchainz commented 2 months ago

@tim-schilling @UnknownPlatypus I would appreciate any pre- or post-merge code review, but no pressure.

adamchainz commented 2 months ago

@David-Wobrock As the author of the change to Django (two years ago!), perhaps you’d like to have a peek? 😇

UnknownPlatypus commented 2 months ago

Not much to say, looking good and the results on sentry are looking good also! I tried it on a few personal repo and it worked as expected on the few matches!

adamchainz commented 2 months ago

Thank you for testing!