【问题标题】:Django model field storing a function or class存储函数或类的 Django 模型字段
【发布时间】:2014-01-03 20:50:52
【问题描述】:

是否可以创建引用函数或类而不是模型的 Django 自定义模型字段?

如果您想知道我为什么想要这个,这里是我想要达到的目标的简要说明。

基本上我有一个 FreightTable 模型,用于计算运费的价值,所以它应该有方法来做到这一点。但问题是有几种不同的计算方式,FreightTable 的每个实例都应该按照特定的方式计算。

起初我考虑使用某种多态性来解决这个问题,但后来我必须为每个不同的算法创建一个特定的模型,而且它们也会在数据库的不同表中,这对我来说是个问题.我也考虑过使用Django Polymorphic,但听说它的扩展性不太好,所以这也不是一个好主意。

我的想法是,如果我可以在模型字段上引用这些不同的算法,我将有一个优雅而有效的解决方案。

【问题讨论】:

  • 计算是否总是产生相同类型的输出(整数、字符串等?)
  • 是的,它总是会产生一个小数

标签: django django-models custom-fields


【解决方案1】:

我的想法是,如果我可以参考这些不同的算法 在模型字段上

这是个好主意,例如:

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

现在,您可以为每种运费类型设置计算方法:

ft = FreightType(calculation_type=2)
ft.save()

在要显示计算结果的地方,从实例中获取方法,然后调用相应的方法:

call_map = {1: 'calc_normal', 2: 'calc_express'}
ft = FreightTable.objects.get(pk=1)
calculated_value = getattr(ft, call_map(ft.calculation_type))()

【讨论】:

  • 谢谢,这就是我要找的!
  • 第二组代码中的 FreightType 应该是 FreightTable 吗?
【解决方案2】:

Python 类、函数和方法不能被pickle,因此你不能将代码本身存储在数据库中。

你能做的是

1) 将函数的完整虚线路径存储在 CharField 中。然后使用zope.dottedname包解析对函数的引用,并调用它。

2) 将计算代码作为 Python 源代码以纯文本形式存储在数据库中。然后通过eval()执行或者使用imp模块动态导入模块

我不确定 Django 是否有内部点名解析器,您可以使用它来代替 zope.dottedname。

【讨论】:

  • 第二种方案看起来很麻烦,但第一个很有趣,不知道这个包
  • 虽然 Zope 这个名字在很多 Python 开发者中被厌恶,但他们是模块化 Python 组件的先驱,而且包中有许多经过十年验证的战斗经验的宝石 :)
猜你喜欢
  • 2017-09-20
  • 2016-02-11
  • 2022-01-04
  • 2017-08-26
  • 2010-10-12
  • 2012-03-29
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多