Repository: django/django

Issue:
# Fixed #36893 -- Serialized elidable kwarg for RunSQL and RunPython operations.

#### Trac ticket number
<!-- Replace XXXXX with the corresponding Trac ticket number. -->
<!-- Or delete the line and write "N/A" if this is a trivial PR. -->

ticket-36893

#### Branch description

Fixed an issue where `elidable=True` was not being serialized for Run-SQL and Run-Python operations which caused these operations to lose their elidable status when written to a migration file (e.g., during squashing), reverting to the default `False`.

-Updated deconstruct() for both Run-SQL and Run-Python to correctly include 'elidable' keyword when set to 'True' 
-Regression Tests are test_run_sql_elidable , test_run_python_elidable and test_operations.py

#### AI Assistance Disclosure (REQUIRED)
<!-- Please select exactly ONE of the following: -->
- [ ] **No AI tools were used** in preparing this PR.
- [x] **If AI tools were used**, I have disclosed which ones, and fully reviewed and verified their output.
Assistance provided by Google DeepMind's Antigravity agent. I used the agent to understand the issue, implement the fix, and add regression tests.
#### Checklist
- [x] This PR follows the [contribution guidelines](https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/submitting-patches/).
- [x] This PR **does not** disclose a security vulnerability (see [vulnerability reporting](https://docs.djangoproject.com/en/stable/internals/security/)).
- [x] This PR targets the `main` branch. <!-- Backports will be evaluated and done by mergers, when necessary. -->
- [x] The commit message is written in past tense, mentions the ticket number, and ends with a period.
- [x] I have checked the "Has patch" ticket flag in the Trac system.
- [ ] I have added or updated relevant tests.
- [ ] I have added or updated relevant docs, including release notes if applicable.
- [ ] I have attached screenshots in both light and dark modes for any UI changes.


Implementation patch:
diff --git a/django/db/migrations/operations/special.py b/django/db/migrations/operations/special.py
index 07000233253c..311271483ea9 100644
--- a/django/db/migrations/operations/special.py
+++ b/django/db/migrations/operations/special.py
@@ -93,6 +93,8 @@ def deconstruct(self):
             kwargs["state_operations"] = self.state_operations
         if self.hints:
             kwargs["hints"] = self.hints
+        if self.elidable:
+            kwargs["elidable"] = self.elidable
         return (self.__class__.__qualname__, [], kwargs)
 
     @property
@@ -173,6 +175,8 @@ def deconstruct(self):
             kwargs["atomic"] = self.atomic
         if self.hints:
             kwargs["hints"] = self.hints
+        if self.elidable:
+            kwargs["elidable"] = self.elidable
         return (self.__class__.__qualname__, [], kwargs)
 
     @property


Test patch:
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index ec4b772c13ed..235804adab60 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -5536,6 +5536,10 @@ def test_run_sql(self):
         elidable_operation = migrations.RunSQL("SELECT 1 FROM void;", elidable=True)
         self.assertEqual(elidable_operation.reduce(operation, []), [operation])
 
+        # Test elidable deconstruction
+        definition = elidable_operation.deconstruct()
+        self.assertIs(definition[2]["elidable"], True)
+
     def test_run_sql_params(self):
         """
         #23426 - RunSQL should accept parameters.
@@ -5789,6 +5793,10 @@ def create_shetlandponies(models, schema_editor):
         elidable_operation = migrations.RunPython(inner_method, elidable=True)
         self.assertEqual(elidable_operation.reduce(operation, []), [operation])
 
+        # Test elidable deconstruction
+        definition = elidable_operation.deconstruct()
+        self.assertIs(definition[2]["elidable"], True)
+
     def test_run_python_invalid_reverse_code(self):
         msg = "RunPython must be supplied with callable arguments"
         with self.assertRaisesMessage(ValueError, msg):