python - 如何在 Django 中创建/使用自定义数据库函数

标签 python django database geodjango django-database-functions

序言:

这是 SO 中经常出现的问题:

并且可以应用于以上以及以下:

我想在 SO 文档上写一个例子,但由于它在 2017 年 8 月 8 日被关闭,我将听从 this widely upvoted and discussed meta answer 的建议,并将我的例子写成一个 self 回答的帖子。

当然,我也很乐意看到任何不同的方法!!


问题:

Django/GeoDjango 有一些数据库函数,比如 Lower()MakeValid(),可以这样使用:

Author.objects.create(name='Margaret Smith')
author = Author.objects.annotate(name_lower=Lower('name')).get()
print(author.name_lower)

有没有什么方法可以根据现有的数据库函数使用和/或创建我自己的自定义数据库函数,例如:

如何在 Django/GeoDjango ORM 中应用/使用这些函数?

最佳答案

Django 提供了 Func() 便于在查询集中调用数据库函数的表达式:

Func() expressions are the base type of all expressions that involve database functions like COALESCE and LOWER, or aggregates like SUM.

关于如何在 Django/GeoDjango ORM 中使用数据库函数有 2 个选项:

为方便起见,我们假设模型名为 MyModel并且子字符串存储在名为 subst 的变量中:

from django.contrib.gis.db import models as gis_models

class MyModel(models.Model):
    name = models.CharField()
    the_geom = gis_models.PolygonField()
  1. 使用 Func() 直接调用函数:

    我们还需要以下内容才能使我们的查询正常工作:

    查询:

    MyModel.objects.aggregate(
        pos=Func(F('name'), Value(subst), function='POSITION')
    )
    
  2. 创建您自己的数据库函数扩展 Func :

    我们可以扩展Func类来创建我们自己的数据库函数:

    class Position(Func):
        function = 'POSITION'
    

    并在查询中使用它:

    MyModel.objects.aggregate(pos=Position('name', Value(subst)))
    

GeoDjango 附录:

GeoDjango , 为了导入 GIS 相关函数(如 PostGISTransform 函数) Func() 方法必须替换为 GeoFunc() , 但它本质上是在相同的原则下使用的:

class Transform(GeoFunc):
    function='ST_Transform'

GeoFunc还有更复杂的情况这里出现了一个有趣的用例:How to calculate Frechet Distance in Django?


泛化自定义数据库函数附录:

如果您想创建一个自定义数据库函数(选项 2)并且您希望能够在事先不知道的情况下将其用于任何数据库,您可以使用 Funcas_<database-name>方法,前提是您要使用的函数存在于每个数据库中:

class Position(Func):
    function = 'POSITION' # MySQL method

    def as_sqlite(self, compiler, connection):
        #SQLite method
        return self.as_sql(compiler, connection, function='INSTR')

    def as_postgresql(self, compiler, connection):
        # PostgreSQL method
        return self.as_sql(compiler, connection, function='STRPOS')

关于python - 如何在 Django 中创建/使用自定义数据库函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46689979/

相关文章:

python - pip 差错误 : 'module' object has no attribute 'Cryptography_HAS_SSL_ST'

django - 来自查询集/通用 View 的下一个先前链接

Django:RunSQL:使用 PostgreSQL COPY 命令

mongodb - 如何更改mongodb集合中字段的类型

Python 和 sqlite3 - 将文本文件导入数据库

python - 在 pandas 中聚合多个数据类型时如何获得一致的行为?

python - PyUSB 无法识别特定的 USB 设备

python - Django FileField 不与 Python 3 的 csv 模块合作

mysql重启自动int主键

Python - 字典可以有一个列表值吗?