我正在试图弄清楚如何构造一个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()的直接问题,我仍然想知道长期的高级解决方案。
答案 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函数。