[Fixed]-What's the purpose of Django "deconstruct" model field function?

32👍

The deconstruct() method is used to help perform model migrations that aren’t able to automatically be handled by the system. Let’s walk through a scenario where deconstruct would get called.

Let’s say we had some model, and we added a custom field to it. The we try to migrate with python manage.py makemigrations.

We encounter the following error:

ValueError: Cannot serialize: Foo
There are some values Django cannot serialize into migration files.

It turns out that there’s already a related ticket that’s been filed with the Django Project, let’s check it out.

ticket-issue

One of the core developers responded that this is intended behavior, because our field contains a callable.

ticket-resolution

So, we missed something in the documentation. There’s a callable value being stored, and it can’t be automatically migrated for some reason. What can we do?

Well, in addition to telling us about the ValueError, manage.py also gave us a useful link to the documentation:

docs-link

Once on that page, scroll down a bit, until we get to the section about serializing values.

Django can serialize the following:

  • Anything with a custom deconstruct() method (see below)

Well, let’s see below:

You can let Django serialize your own custom class instances by giving
the class a deconstruct() method. It takes no arguments, and should
return a tuple of three things (path, args, kwargs):

  • path should be the Python path to the class, with the class name
    included as the last part (for example, myapp.custom_things.MyClass).
    If your class is not available at the top level of a module it is not
    serializable.
  • args should be a list of positional arguments to pass to
    your class’ init method. Everything in this list should itself be
    serializable.
  • kwargs should be a dict of keyword arguments to pass to
    your class’ init method. Every value should itself be
    serializable.

Note that the deconstruct() method works hand in hand with __eq__(), as stated by the documentation:

To prevent a new migration from being created each time makemigrations is run, you should also add a __eq__() method to the decorated class. This function will be called by Django’s migration framework to detect changes between states.

In my case, the mistake was adding parenthesis after a value that should not have been called, but in many cases you’ll want to implement that deconstruct method for migrations. (Here’s another useful link that has an example.)

👤Moshe

Leave a comment