Aliasing Django model property
Not a super common occurrence, but exposing a Django model property under an alternative name is occasionally useful. I have used it before to assist in polymorphism, where several very similar models needed to have the same attribute.
Given a Django model like:
from django.db import models
class Widget(models.Model):
email = models.CharField(max_length=254)
We can naievy try and alias the attribute by defining an accessor for it:
# ...
class Widget(models.Model):
def username(self):
return self.email
This appears to work - except when we go to use it, we find that Widget().username
isn’t a
property - it’s a callable method. This means that we can’t use it as an alias, since username
would need to be accessed using username()
, while email
would be immediately accessible as
email
.
Fortunately, Python has a method decorator avilable called @property
. This decorator is a way of
signalling to the class that a particular method can be used to get or set an attribute on the
class. We can use the @property
decorator in our Widget
class to alias our attribute nicely now:
from django.db import models
class Widget(models.Model):
email = models.CharField(max_length=254)
@property
def username(self):
return self.email
And we can access the email using either widget.email
OR widget.username
. Nice!
If you wish this alias to be bound in both directions (getting the attribute as well as setting the value), this is also possilble, you just need to define an additional method:
from djang.db import models
class Widget(models.Model):
email = models.CharField(max_length=254)
@property
def username(self):
return self.email
@username.setter
def set_username(self, username):
self.email = username