Opened 7 weeks ago

Last modified 6 weeks ago

#35813 assigned Bug

Makemigrations not properly tracking changes to unmanaged models — at Initial Version

Reported by: Hanny G Owned by:
Component: Migrations Version: 5.1
Severity: Normal Keywords: makemigrations, unmanaged
Cc: Hanny G, Simon Charette, Imran Ahmed Khan Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I believe there is a bug with the makemigrations command.

The Issue/Bug: Changes to unmanaged models are not being recognized by makemigrations. If those same changes are applied to a managed model, makemigrations recognizes the changes.

The makemigrations command tracks the Creation of an unmanaged model, the Deletion of an unmanaged model, but does not track changes to the attributes/fields of an unmanaged model (see example below for more depth).

Concerns/Discussion: If you create an unmanaged model, make the initial migration and then have to change a field on it, makemigrations will not detect the change you made. At that point, your migrations (the 'historical reference') are out of sync with the current reality of the model.

I have an if this is unclear.
For this example let's assume we have two models: UnmanagedThing and ManagedThing (unmanaged and managed, respectively)

class UnmanagedThing(models.Model):
    """
    This model represents an unmanaged Thing.
    """

    id = models.IntegerField(
        db_column="thingID", primary_key=True
    )
    thing_number = models.CharField(max_length=16, db_column="thingNumber")
    thing_name = models.CharField(max_length=50, db_column="thingName")
    grade_level = models.CharField(max_length=2, db_column="gradeLevel")

    class Meta:
        """Meta options for the UnmanagedThing model."""

        verbose_name = "Unmanaged Thing"
        verbose_name_plural = "Unmanaged Things"
        managed = False
        db_table = "some_table_name"

    def __str__(self) -> str:
        """Return the course name."""
        return f"{self.thing_name}"

class ManagedThing(models.Model):
    """
    This model represents an unmanaged Thing.
    """

    id = models.IntegerField(
        db_column="thingID", primary_key=True
    )
    thing_number = models.CharField(max_length=16, db_column="thingNumber")
    thing_name = models.CharField(max_length=50, db_column="thingName")
    grade_level = models.CharField(max_length=2, db_column="gradeLevel")

    class Meta:
        """Meta options for the UnmanagedThing model."""

        verbose_name = "Unmanaged Thing"
        verbose_name_plural = "Unmanaged Things"

    def __str__(self) -> str:
        """Return the course name."""
        return f"{self.thing_name}"

If I run makemigrations I get the expected 0001... migration file and I see both models created with their respective fields/options.

If I change thing_name to be an IntegerField on the managed model and run makemigrations, I see a 0002... migration file created with the expected 'AlterField' inside of it.

If I change thing_name to be an IntegerField on the unmanaged model and run makemigrations, I see "No changes detected" and nothing is created. However, now there is a disconnect between my model and what is recorded in migrations.

Everything else works similarly between the two; if I delete either one, it's recorded in a migration file. If I change the unmanaged model to 'managed', it creates a migration file for that (and subsequently begins tracking changes as expected with makemigrations)

Per the django docs: " You should think of migrations as a version control system for your database schema. makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits"; it's not behaving that way currently, so I believe this to be a valid bug worth fixing if the docs

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top