Heroku, postgreSQL, django, комментарии, tastypie: оператор не соответствует указанному имени и типу аргументов. Возможно, вам придется добавлять явные типы - программирование
Подтвердить что ты не робот

Heroku, postgreSQL, django, комментарии, 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.

После поиска по всему миру эта ошибка была рассмотрена много раз в джанго, но я все еще получаю ее (все связанные проблемы были закрыты 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?

4b9b3361

Ответ 1

Основываясь на ответе 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) "s.

Ответ 2

PostgreSQL "строго типизирован" - то есть каждое значение в каждом запросе имеет определенный тип, явно определенный (например, тип столбца в таблице) или неявно (например, значения, вводимые в предложение WHERE). Все функции и операторы, включая =, должны быть определены как принятие определенных типов - так, например, существует оператор для VarChar = VarChar, а другой для int = int.

В вашем случае у вас есть столбец, который явно определен как тип int, но вы сравниваете его со значением, которое PostgreSQL интерпретировал как тип text.

SQLite, с другой стороны, является "слабо типизированным" - значения свободно рассматриваются как имеющие любой тип, наиболее подходящий для выполняемого действия. Таким образом, в вашей базе данных devite SQL операция '42' = 42 может быть вычислена просто отлично, где PostgreSQL потребуется определенное определение VarChar = int (или text = int, text, являющееся типом для неограниченных строк в PostgreSQL).

Теперь PostgreSQL иногда будет полезен и автоматически "отбрасывает" ваши значения, чтобы типы соответствовали известному оператору, но чаще, как подсказывает подсказка, вам нужно сделать это явно. Если вы сами пишете SQL, явный тип case может выглядеть как WHERE id = CAST('42' AS INT) (или WHERE CAST(id AS text) = '42').

Так как вы этого не сделали, вам нужно убедиться, что ввод, который вы передаете генератору запросов, является фактическим целым числом, а не просто строкой, состоящей из цифр. Я подозреваю, что это так же просто, как использование fields.IntegerField, а не fields.CharField, но я действительно не знаю Django или даже Python, поэтому я думал, что дам вам фон в надежде, что вы сможете его оттуда оттуда.