Reputation: 3453
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
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 calledto_python()
on assignment. This did not play nicely with custom database transformations, aggregation, or values queries, so it has been replaced withfrom_db_value()
.
Upvotes: 1