如何在Django中使用MySQL用户定义函数(UDF)?

时间:2011-04-18 15:00:25

标签: mysql django user-defined-functions

我正在试图弄清楚如何构造一个Django过滤器,其中包含依赖于MySQL中定义的用户定义函数(UDF)的术语。

我的UDF处理称为化学信息学的计算化学分支。其中一个函数(oe_matches)让我测试子结构(表示为“SMARTS”字符串)是否与结构匹配(表示为“SMILES”字符串)。您可以将这些视为与匹配字符串的正则表达式同构。

在我的数据库中,我有一个名为“节点”的主题表。其中包含有关研究主题的可搜索文本。该主题中的一些信息涉及分子。我有一张分子表。分子可以在多个主题中,主题可以是多于一个分子,所以我有:

class Node(models.Model):
    title = models.CharField()
    content = models.CharField()

class Structure(models.Model):
    smiles = models.CharField(max_length=255)
    nodes = models.ManyToManyField(Node)

现在我想搜索标题或内容中具有“test”的所有节点,匹配SMARTS模式“[C;!H0]”(即带有at的碳)至少一个氢)。

理想情况下,我想写如下:

q = ((models.Q(title__icontains="test") |
      models.Q(content__icontains="test")
     ).filter(models.Q(structure__node_smiles = oe_match(smarts="[C;!H0]")))
    )

其中oe_match是知道如何为MySQL生成正确的后端代码的东西,在本例中是'oe_match(“[C;!H0]”,Structure.smiles)'和Django在哪里看到结构_node_smiles并且执行它多种多样的魔力使部件组合在一起。

我看到我可以通过raw()接口得到我想要的东西(模数小语法错误并使用错误的连接类型):

SELECT * FROM Node, Node_Structure, Structure WHERE
     ((Node.title LIKE "%test%" OR Node.content LIKE "%test%") AND
      (Node.id = Node_Structure.node AND
       Node_Structure.structure = Structure.id) AND
      oe_matches("[C;!H0]", Structure.smiles));

我宁愿不以这种方式混合和匹配我的数据库层。另外,我将不得不做一些代码重组。 (目前我创建了一个过滤器,我稍后将其传递给模型进行搜索。)

从长远来看,我希望其他人将我的MySQL UDF用于化学信息学,我认为我的潜在用户(除了我工作的其他两个人)之外的一些高级Django调用会很好,所以即使我可以解决raw()的直接问题,我仍然想知道长期的高级解决方案。

2 个答案:

答案 0 :(得分:0)

使用QuerySet.extra,很乐意接受您的自定义功能(使用where关键字参数)。

http://docs.djangoproject.com/en/1.3/ref/models/querysets/#extra

答案 1 :(得分:0)

当我问这个问题时,我在学校的时候回答这个问题太晚了。我们可以使用django提供的Func方法来使用custom(用户定义函数)功能。

from django.db.models import Func

class MultiArgFunc(Func):
    def __init__(self, *expressions):
        super().__init__(*expressions)

class NextShardID(MultiArgFunc):
    function = "next_shard_id"

现在,您可以在任何喜欢的地方使用NextShardID函数。