2013-04-16 4 views
14

ich eine einfache Abfrage auf Djangos in den Kommentaren Modell gebaut habe und immer die Fehler unten mit Heroku des PostgreSQL-Datenbank:heroku, postgreSQL, django, Kommentare, tastypie: Kein Operator entspricht dem angegebenen Namen und Argumenttyp (en). Möglicherweise müssen expliziten Typen hinzufügen wirft

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. 

Nach googeln um es dieser Fehler oft angesprochen scheint wurde vorher im Django, aber ich bekomme es immer noch (alle damit verbundenen Probleme wurden vor 3-5 Jahren geschlossen). Ich benutze Django Version 1.4 und die neueste Version von Tastypie.

Die Abfrage wird unter orm Filter gemacht und arbeitet perfekt mit meiner Entwicklung Datenbank (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) 

Jeder mit keiner Erfahrung haben, ohne das Schreiben rohes SQL, um diesen Fehler zu bekommen?

+0

Wie der Fehler sagt, versuchen Sie eine Ganzzahl mit einem Textwert zu vergleichen. Hör auf damit und der Fehler wird verschwinden. –

+0

Übrigens ist dies ein gutes Beispiel dafür, warum Tests mit einer Umgebung durchgeführt werden sollten, die so ähnlich wie möglich ist: Wie sehr auch immer ein Framework abstrahiert, etwas, das so komplex ist wie ein DBMS, muss ein anderes Verhalten und Einschränkungen haben . – IMSoP

+0

IMSoP, ja, ich habe diese Lektion heute gelernt! Habe gerade meine Entwicklungsdatenbank auf PostgreSQL umgestellt, um an diesem Problem zu arbeiten. – arctelix

Antwort

4

Aufbauend auf der Antwort von IMSoP: Dies ist eine Einschränkung der ORM-Ebene von django, wenn ein generischer Fremdschlüssel ein Textfeld für die Objekt-ID verwendet und das ID-Feld des Objekts kein Textfeld ist. Django möchte keine Annahmen machen oder die ID des Objekts als etwas ausgeben, das es nicht ist. Ich fand einen ausgezeichneten Artikel über diese http://charlesleifer.com/blog/working-around-django-s-orm-to-do-interesting-things-with-gfks/.

Der Autor des Artikels, Charles Leifer kam mit einer sehr coolen Lösung für Abfragen, die davon betroffen sind und wird sehr hilfreich sein, um mit diesem Problem voranzukommen.

Alternativ konnte ich meine Frage bekommen, wie folgt zu arbeiten:

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 

Ursprünglich ich für eine Art und Weise wurde die Suche im SQL ähnlich wie zu ändern, was Charles getan hat, aber es stellt sich heraus, alles, was ich musste Do war die Abfrage in zwei Teile zu brechen und die Str (ID) zu Int (ID) zu konvertieren.

29

PostgreSQL ist "stark typisiert" - dh jeder Wert in jeder Abfrage hat einen bestimmten Typ, entweder explizit definiert (z. B. der Typ einer Spalte in einer Tabelle) oder implizit (z. B. die in eine WHERE-Klausel eingegebenen Werte) . Alle Funktionen und Operatoren, einschließlich =, müssen so definiert sein, dass sie bestimmte Typen akzeptieren. So gibt es beispielsweise einen Operator für VarChar = VarChar und einen anderen für . In Ihrem Fall haben Sie eine Spalte, die explizit als Typ int definiert ist, aber Sie vergleichen sie mit einem Wert, den PostgreSQL als Typ text interpretiert hat.

SQLite dagegen ist "schwach typisiert" - Werte werden frei behandelt, als ob sie von dem Typ sind, der am besten für die ausgeführte Aktion geeignet ist. So kann in Ihrer SQLite-Dev-Datenbank die Operation '42' = 42 einfach berechnet werden, wobei PostgreSQL eine spezifische Definition von VarChar = int (oder text = int, text als Typ für unbegrenzte Strings in PostgreSQL) benötigt.

Jetzt wird PostgreSQL manchmal hilfreich sein und automatisch Ihre Werte "werfen", damit die Typen einem bekannten Operator entsprechen, aber häufiger, wie der Hinweis sagt, müssen Sie es explizit tun. Wenn Sie den SQL-Code selbst schreiben, könnte ein expliziter Typ-Case wie (oder WHERE CAST(id AS text) = '42') aussehen.

Da dies nicht der Fall ist, müssen Sie sicherstellen, dass die Eingabe, die Sie dem Abfragegenerator geben, eine tatsächliche ganze Zahl ist, nicht nur eine Zeichenfolge, die aus Ziffern besteht. Ich vermute, das ist so einfach wie die Verwendung fields.IntegerField statt , aber ich weiß eigentlich nicht Django, oder sogar Python, also dachte ich, ich würde Ihnen den Hintergrund in der Hoffnung geben, dass Sie es von dort nehmen können.

+0

Vielen Dank für die Informationen, sehr gut und ich verstehe, dass ist, was den Fehler verursacht. Das Problem ist, dass djangos gfk für das Kommentarmodell ein Textfeld für die object_id verwendet und das Objekt, das kommentiert wird, ein integer Feld verwendet. Also sollte die Aufgabe eigentlich gewesen sein, ohne das Kommentarmodell auf Integer zu beschränken IDs. – arctelix

Verwandte Themen