21

我对 django 的内置评论模型有一个简单的查询,并使用 heroku 的 postgreSQL 数据库得到以下错误:

DatabaseError: operator does not exist: integer = text LINE 1: 
... INNER JOIN "django_comments" ON ("pi ns_pin"."id" = "django_...
                                                         ^
HINT:  No operator matches the given name and argument type(s). 
You might need to add explicit type casts.

在谷歌搜索之后,似乎这个错误已经在 django 中多次解决,但我仍然得到它(所有相关问题都在 3-5 年前关闭)。我正在使用 django 1.4 版和最新版本的 sweetpie。

该查询是在 orm 过滤器下进行的,并且可以与我的开发数据库(sqlite3)完美配合:

class MyResource(ModelResource):    

    comments = fields.ToManyField('my.api.api.CmntResource', 'comments', full=True, null=True)

    def build_filters(self, filters=None):
        if filters is None:
            filters = {}

        orm_filters = super(MyResource, self).build_filters(filters)

        if 'cmnts' in filters:
            orm_filters['comments__user__id__exact'] = filters['cmnts']

class CmntResource(ModelResource):
    user = fields.ToOneField('my.api.api.UserResource', 'user', full=True)
    site_id = fields.CharField(attribute = 'site_id')
    content_object = GenericForeignKeyField({
        My: MyResource,
    }, 'content_object')
    username = fields.CharField(attribute = 'user__username', null=True)
    user_id = fields.CharField(attribute = 'user__id', null=True)

有没有人在不编写原始 SQL 的情况下解决此错误的经验?

4

3 回答 3

36

PostgreSQL 是“强类型”的——也就是说,每个查询中的每个值都有一个特定的类型,或者显式定义(例如,表中列的类型)或隐式定义(例如,输入到WHERE子句中的值)。所有函数和运算符,包括=,都必须定义为接受特定类型 - 例如,有一个运算符用于VarChar = VarChar,而另一个运算符用于int = int

在您的情况下,您有一个明确定义为 type 的列int,但是您将它与 PostgreSQL 解释为 type 的值进行比较text

另一方面,SQLite 是“弱类型” - 值被自由地视为最适合正在执行的操作的任何类型。因此,在您的开发 SQLite 数据库中,'42' = 42可以很好地计算操作,其中 PostgreSQL 需要一个特定的定义VarChar = int(或者text = inttext作为 PostgreSQL 中无界字符串的类型)。

现在,PostgreSQL有时会有所帮助并自动“转换”您的值以使类型与已知运算符匹配,但更常见的是,正如提示所说,您需要明确地执行此操作。如果您自己编写 SQL,则显式类型案例可能类似于WHERE id = CAST('42' AS INT)(或WHERE CAST(id AS text) = '42')。

既然你不是,你需要确保你给查询生成器的输入是一个实际的整数,而不仅仅是一个恰好由数字组成的字符串。我怀疑这就像使用fields.IntegerField而不是一样简单fields.CharField,但我实际上并不了解 Django,甚至不了解 Python,所以我想我会给你背景知识,希望你能从那里学到它。

于 2013-04-16T22:03:52.543 回答
7

基于 IMSoP 的回答:当通用外键使用文本字段作为 object_id 并且对象的 id 字段不是文本字段时,这是 django 的 ORM 层的限制。Django 不想做任何假设或将对象的 id 转换为它不是的东西。我在http://charlesleifer.com/blog/working-around-django-s-orm-to-do-interesting-things-with-gfks/上找到了一篇很棒的文章。

这篇文章的作者 Charles Leifer 为受此影响的查询提出了一个非常酷的解决方案,并且在处理这个问题时非常有用。

或者,我设法让我的查询按如下方式工作:

if 'cmnts' in filters:
    comments = Comment.objects.filter(user__id=filters['cmnts'], content_type__name = 'my',   site_id=settings.SITE_ID ).values_list('object_pk', flat=True)
    comments = [int(c) for c in comments]
    orm_filters['pk__in'] = comments

最初我正在寻找一种类似于查尔斯所做的修改 SQL 的方法,但事实证明我所要做的就是将查询分成两部分并将 str(id)'s 转换为 int(id)' s。

于 2013-04-17T04:24:28.973 回答
0

为了不破解您的 ORM 和外部软件 postgres,您可以注册自己的演员表并比较操作。请查看类似问题中的示例

于 2017-05-02T22:56:16.300 回答