我对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版和最新版本的tastypie。
查询是在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的情况下解决此错误的经验?
答案 0 :(得分:32)
PostgreSQL是“强类型”的 - 也就是说,每个查询中的每个值都有一个特定的类型,要么显式定义(例如表中列的类型),要么隐式定义(例如输入{{1}的值}子句)。所有函数和运算符(包括WHERE
)都必须定义为接受特定类型 - 例如,=
有一个运算符,VarChar = VarChar
有一个运算符。
在您的情况下,您有一个显式定义为类型int = int
的列,但您将它与PostgreSQL解释为类型int
的值进行比较。
text
,其中PostgreSQL需要'42' = 42
的特定定义(或VarChar = int
,text = int
是无界的类型PostgreSQL中的字符串)。
现在,PostgreSQL将有时有用并自动“强制转换”您的值以使类型与已知运算符匹配,但更常见的是,正如提示所示,您需要明确地执行此操作。如果您自己编写SQL,则显式类型的情况可能看起来像text
(或WHERE id = CAST('42' AS INT)
)。
既然你没有,你需要确保你给查询生成器的输入是一个实际的整数,而不仅仅是一个恰好由数字组成的字符串。我怀疑这就像使用WHERE CAST(id AS text) = '42'
而不是fields.IntegerField
一样简单,但我实际上并不知道Django,甚至Python,所以我想我会给你背景,希望你能拿走从那里开始。
答案 1 :(得分:4)
基于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
最初我正在寻找一种类似于Charles所做的修改SQL的方法,但事实证明我所要做的就是将查询分成两部分并将str(id)转换为int( ID)的
答案 2 :(得分:0)
不要破解你ORM和外部软件postgres允许你注册自己的演员阵容并比较操作。 Please look example in similar question