heroku, postgreSQL, django, comments, tastypie: ни один оператор не соответствует заданному имени и типу аргументов. Возможно, Вам потребуется добавить явные приведения типов
у меня есть простой запрос на встроенную модель комментариев django и получение ошибки ниже с базой данных postgreSQL heroku:
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.
после googling вокруг кажется, что эта ошибка была решена много раз раньше в 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)
у кого-нибудь есть опыт обхода этой ошибки без написания raw SQL?
3 ответов
PostgreSQL "строго типизирован" - то есть каждое значение в каждом запросе имеет определенный тип, либо определенный явно (например, тип столбца в таблице), либо неявно (например, значения, введенные в WHERE
предложения). Все функции и операторы, включая =
, должны быть определены как принимающие определенные типы-так, например, есть оператор для VarChar = VarChar
, а другой int = int
.
в вашем случае, у вас есть столбец, который однозначно определяется как тип int
, но вы сравниваете его со значением, которое PostgreSQL интерпретировал как type text
.
SQLite, с другой стороны, является" слабо типизированным " - значения свободно рассматриваются как имеющие тот тип, который лучше всего подходит для выполняемого действия. Таким образом, в вашей базе данных dev SQLite операция '42' = 42
можно вычислить просто отлично, где PostgreSQL потребуется конкретное определение VarChar = int
(или text = int
, text
быть типом для неограниченных строк в PostgreSQL).
теперь, PostgreSQL будет иногда будьте полезны и автоматически "приведите" свои значения, чтобы типы соответствовали известному оператору, но чаще, как говорится в подсказке, вам нужно сделать это явно. Если вы сами пишете SQL, явный случай типа может выглядеть как WHERE id = CAST('42' AS INT)
(или WHERE CAST(id AS text) = '42'
).
поскольку вы не, вам нужно убедиться, что ввод, который вы даете генератору запросов, является фактическим целым числом, а не просто строкой, которая происходит с состоят из цифр. Я подозреваю, что это так же просто, как использовать fields.IntegerField
, а не fields.CharField
, но я на самом деле не знаю Django или даже Python, поэтому я подумал, что дам вам фон в надежде, что вы можете взять его оттуда.
основываясь на ответе IMSoP: это ограничение слоя ORM django, когда общий внешний ключ использует текстовое поле для object_id, а поле id объекта не является текстовым полем. Django не хочет делать никаких предположений или бросать идентификатор объекта как то, что это не так. Я нашел отличную статью об этом http://charlesleifer.com/blog/working-around-django-s-orm-to-do-interesting-things-with-gfks/.
автор статьи Чарльз Лейфер пришел с очень крутым решением для запросов, которые затронуты этим и будут очень полезны при решении этой проблемы.
кроме того, мне удалось заставить мой запрос работать следующим образом:
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) в int(id).
чтобы не взломать вас ORM и внешнее программное обеспечение postgres позволяют регистрировать свои собственные слепки и сравнивать операции. пожалуйста, посмотрите пример в аналогичном вопросе.