heroku、postgreSQL、django、comments、tastypie:没有与给定名称和参数类型匹配的运算符。您可能需要添加显式类型转换
我对django的内置注释模型进行了一个简单的查询,并通过heroku的postgreSQL数据库得到以下错误:heroku、postgreSQL、django、comments、tastypie:没有与给定名称和参数类型匹配的运算符。您可能需要添加显式类型转换,django,postgresql,heroku,tastypie,django-comments,Django,Postgresql,Heroku,Tastypie,Django Comments,我对django的内置注释模型进行了一个简单的查询,并通过heroku的postgreSQL数据库得到以下错误: DatabaseError: operator does not exist: integer = text LINE 1: ... INNER JOIN "django_comments" ON ("pi ns_pin"."id" = "django_... ^ HI
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和最新版本的tastypie
该查询在orm过滤器下进行,并与我的开发数据库(sqlite3)完美配合:
有没有人有过在不编写原始SQL的情况下绕过此错误的经验?PostgreSQL是“强类型”的,即每个查询中的每个值都有一个特定的类型,可以是显式定义的(例如表中列的类型),也可以是隐式定义的(例如,输入到WHERE
子句中的值)。所有函数和运算符,包括=
,都必须定义为接受特定类型-例如,VarChar=VarChar
有一个运算符,而int=int
有一个不同的运算符
在您的例子中,有一个列被显式定义为typeint
,但您将它与PostgreSQL解释为typetext
的值进行比较
另一方面,SQLite是“弱类型的”——值被自由地视为最适合所执行操作的任何类型。因此,在dev SQLite数据库中,可以很好地计算操作'42'=42
,其中PostgreSQL需要一个特定的VarChar=int
(或者text=int
,text
是PostgreSQL中无界字符串的类型)
现在,PostgreSQL有时会很有帮助,会自动“强制转换”您的值,以使类型与已知运算符匹配,但更常见的是,正如提示所说,您需要显式地执行此操作。如果您自己编写SQL,显式类型的大小写可能类似于WHERE-id=CAST('42'为INT)
(或WHERE-CAST(id为text)='42'
)
因为不是,所以需要确保给查询生成器的输入是实际的整数,而不仅仅是碰巧由数字组成的字符串。我猜想这就像使用
fields.IntegerField
而不是fields.CharField
一样简单,但我实际上不知道Django,甚至不知道Python,所以我想我会给你背景,希望你能从那里得到它。基于IMSoP的答案:当通用外键使用对象id的文本字段而对象的id字段不是文本字段时,这是django的ORM层的一个限制。Django不想做任何假设,也不想将对象的id转换为它不是的东西。我发现了一篇关于这方面的优秀文章
这篇文章的作者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,类似Charles所做的,但结果证明我所要做的就是将查询分为两部分,并将str(id)转换为int(id)。为了不攻击ORM,外部软件postgres允许您注册自己的强制转换和比较操作 正如错误所说,您试图将整数与文本值进行比较。停止这样做,错误就会消失。顺便说一句,这是一个很好的例子,说明了为什么测试应该在与部署环境尽可能相似的环境中进行:无论框架声称对其进行了多少抽象,像DBMS这样复杂的东西必然会有不同的行为和限制。IMSoP,是的,我今天确实学到了这个教训!刚刚把我的开发数据库改成PostgreSQL来处理这个问题。哇,超过2900个视图,没有一次投票。。。我猜2900人觉得这个问题没用。5243还有计数……谢谢你的信息,说得很好,我明白这就是导致错误的原因。问题是django的gfk for The comments模型使用一个文本字段作为object_id,而被注释的对象使用一个整数字段。。因此,真正的问题应该是如何在不将注释模型限制为整数id的情况下绕过这个问题。
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