3👍
But once I exit the shell, I loose the property. Is there any way to add the property permanently.
No, not through attributes you set at run-time. Data associated with Django model instances is persisted through the database. Your only option for persisting data is to create a field in the database with which to store the information. If you want to persist methods available on a class, edit the source code.
You’ve expressed a desire to do this dynamically at runtime, too. However, the benefit of doing so is dubious, at best, and likely hazardous to your code base. It’s hard to imagine a demonstrable use-case where this solves a real problem that does not already have a better solution. There is almost certainly a better way to get at your goal. If your goal is to keep your code DRY, consider other patterns like inheriting from abstract models.
You can implement regular properties (using the @property
method decorator) on your model class that can take existing fields and look at related model fields to compose information on-the-fly, but it is still not persisted in the database…
For example, if you have a model that has a start_time
and end_time
you could add a total_time
property without necessarily needing to create a field for it.
class MyModel(models.Model):
start_time = models.DateTimeField()
end_time = models.DateTimeField()
@property
def total_time(self):
return self.end_time - self.start_time
However, doing this would not allow you to query against this property. MyModel.objects.filter(total_time__lt=delta)
for example would not be possible with a property alone.
Some other options you have include annotation and aggregation which can be done dynamically at run-time and gives you the benefit of being able to query against your database.
Using the same example as above, rather than using @property
one can annotate a queryset in a similar way, which also lets you query the database on this ‘virtual field’ and even pass that annotated queryset around. You can even do arithmetic and aggregations like sum, average, and more…
from django.db.models import F, ExpressionWrapper, fields
duration = ExpressionWrapper(F('end_time') - F('start_time'), output_field=fields.DurationField())
qs = MyModel.objects.annotate(duration=duration)
# query for objects with a delta of more than five minutes
results = qs.filter(duration__gt=five_minutes)
See also Query expressions
In short: no, and if you could, it’s almost definitely a bad idea. Stick with the established methods of doing things. Django is a very opinionated framework, it is designed for you to do things ‘the django way’. You will likely only hurt yourself by going against the grain.