Brendan W
Brendan W

Reputation: 3453

In a django custom field, what does the SubfieldBase metaclass do?

When you implement a custom Django field, you're supposed to include this line:

__metaclass__ = models.SubfieldBase

in the class definition, as in:

class SomeCustomField(models.Field):
    __metaclass__ = models.SubfieldBase

What does that actually do?

Update:

This is the source code for the metaclass (from the Django project):

class SubfieldBase(type):
    """
    A metaclass for custom Field subclasses. This ensures the model's attribute
    has the descriptor protocol attached to it.
    """
    def __new__(cls, name, bases, attrs):
        new_class = super(SubfieldBase, cls).__new__(cls, name, bases, attrs)
        new_class.contribute_to_class = make_contrib(
            new_class, attrs.get('contribute_to_class')
        )
        return new_class

How does that cause to_python to be called? And what would be called otherwise?

Upvotes: 2

Views: 1805

Answers (1)

Rahul Gupta
Rahul Gupta

Reputation: 47846

For Django versions<=1.7, Django provides a metaclass called SubfieldBase.

The main feature of SubFieldBase is that is calls to_python() on assignment. So, when you added a __metaclass__, it will automatically call the to_python() function to convert the value into the correct Python object. It handles those fields where type conversion is needed when loading from the database but is not used in .values() calls or in aggregates.

This has been changed in Django 1.8 though. It has been replaced with from_db_value().

As per the Django 1.8 docs:

Historically, Django provided a metaclass called SubfieldBase which always called to_python() on assignment. This did not play nicely with custom database transformations, aggregation, or values queries, so it has been replaced with from_db_value().

Upvotes: 1

Related Questions