What is deconstructible?

deconstructible

As it is written in the docstrings of deconstructible, this decorator allows your classes to be serialized by the migrations subsystem in Django.

What does it mean?

You want to use custom-written classes in your model fields and you wait for migrations to be created without any problem. Well, to use your models you need to migrate first, and your custom classes should be serializable to play part in the migrations. Otherwise, it’ll fail. To get more information about what I want to explain you can look at Django documents here.

Let me give an example.

I’ll be using djongo’s GridFSStorage class to write a simple example.

GridFSStorage is written with the @deconstructible decorator as can be seen in the source code. For brevity, I won’t include the all bricks of the class:

@deconstructible
class GridFSStorage(Storage):
    def __init__(self, location='', collection='storage', database='default',
                 base_url=None):
        self.location = location.strip(os.sep)
        self.collection = collection
        self.database = database
        self.base_url = base_url
        ....

I created a Brand model and I want to store brand logos in myfiles collection in MongoDB:

from djongo.storage import GridFSStorage
grid_fs_storage = GridFSStorage(collection='myfiles')

# ...

class Brand(models.Model):
    name = models.CharField(
        max_length=128, blank=False, null=False, unique=True
    )
    logo = models.ImageField(upload_to=grid_fs_storage, blank=True, null=True)

and I run the migrations afterwards. Migration is applied successfully and the created migration file is this:

from django.db import migrations, models
import djongo.storage


class Migration(migrations.Migration):

    initial = True

    dependencies = []

    operations = [
        migrations.CreateModel(
            name="Brand",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("name", models.CharField(max_length=128, unique=True)),
                (
                    "logo",
                    models.ImageField(
                        blank=True,
                        null=True,
                        upload_to=djongo.storage.GridFSStorage(collection="myfiles"),
                    ),
                ),
            ],
        ),
    ]

I deleted the @deconstructible line at the top of GridFSStorage class and run anew migrate but I got an error:

    raise ValueError(
ValueError: Cannot serialize: <djongo.storage.GridFSStorage object at 0x7f8c008ca680>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/4.1/topics/migrations/#migration-serializing

As you see, your custom classes in your model fields should be deconstructible.

See you in the next article 🙂