Is it possible to create a Django Custom Model Field that references a function or class, instead of a model?
In case you're wondering why i would want this, here's a brief explanation of waht i'm trying to achieve.
Basically i have a FreightTable model, that is used to calculate the value of a freight, so it should have method to do this. But the problem is that there are several different ways to calculate it, and each instance of the FreightTable should calculate on its specific way.
At first i thought about solving this using some kind of polymorphism, but then i would have to create an specific model for each different algorithm, and they would also be in different tables in the DB, what would be a problem for me. I also thought about using Django Polymorphic, but i heard it doesnt really scale well, so it's also not a good idea.
My thought is that if I could just reference this different algorithms on a Model Field, I'll have an ellegant and eficient solution.
My thought is that if I could just reference this different algorithms on a Model Field
This is a good idea, for example:
CALCULATION_TYPES = [(1, 'Normal'), (2, 'Express')]
class FreightTable(models.Model):
# Normal fields
calculation_type = models.IntegerField(choices=CALCULATION_TYPES)
def calc_normal(self):
pass
def calc_express(self):
pass
def calc_default(self):
pass
Now, for each freight type, you set your calculation method:
ft = FreightType(calculation_type=2)
ft.save()
At the point where you want to display the result of the calculation, fetch the method from the instance, and then call the appropriate method:
call_map = {1: 'calc_normal', 2: 'calc_express'}
ft = FreightTable.objects.get(pk=1)
calculated_value = getattr(ft, call_map(ft.calculation_type))()
Python classes, functions and methods cannot be pickled, so you cannot store the code itself in the database.
What you can do is
1) Store the full dotted path to the function in a CharField. Then resolve the reference to function using zope.dottedname package, and call it.
or
2) Store the calculation code as Python source code in the database as plain text. Then execute it through eval() or dynamic module import using imp module
I am not sure if Django had internal dotted name resolver, you could use it instead of zope.dottedname.
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