Question

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.

Was it helpful?

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))()

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top