I want to add custom attributes to instances of a Django model. These attributes should not be stored in the database. In any other class, the attributes would simply be initialized by the __init__
method.
I can already see three different ways to do it, and none of them are completely satisfying. I wonder if there is any better/more pythonic/djangoist way to do it?
Override the __init__
method: the syntax is a bit convoluted, but it works.
from django.db.models import Model
class Foo(Model):
def __init__(self, *args, **kwargs):
super(Model, self).__init__(*args, **kwargs)
self.bar = 1
Use a Django post_init
signal: this takes class code outside of the class definition, which is not very readable.
from django.dispatch import receiver
from django.db.models.signals import post_init
@receiver(post_init, sender=Foo)
def user_init(sender, instance, *args, **kwargs):
instance.bar = 1
Use an instance method instead of an attribute: having a general exception raised as the default behaviour is a bit disturbing.
class Foo(Model):
def bar(self):
try:
return self.bar
except:
self.bar = 1
return self.bar
Of these three choices, the first looks like the least worst to me. What do you think? Any alternative?
To create a new instance of a model, instantiate it like any other Python class: class Model (**kwargs) The keyword arguments are the names of the fields you've defined on your model. Note that instantiating a model in no way touches your database; for that, you need to save() .
To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() .
def __str__( self ): return "something" This will display the objects as something always in the admin interface. Most of the time we name the display name which one could understand using self object.
In Django , a model field pertains to a column in the database. On the other hand, a model attribute pertains to a method or property that is added to a model .
I would use the property decorator available in python
class Foo(Model):
@property
def bar(self):
if not hasattr(self, '_bar'):
self._bar = 1
return self._bar
Then you can access that just like a property instead of invoking a function with ()
You could even get a little more straight forward with this by having the fallback built in, instead of stored
class Foo(Model):
@property
def bar(self):
return getattr(self, '_bar', 1)
Overriding __init__
is the right way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With