2012-02-22 3 views
3

je tente de faire une requête brute sur mesure pour un modèle et je reçois cette erreur:problèmes avec django paramètres de requête brute

DatabaseError: error de sintaxis en o cerca de «E'positions_statusrecord'» LINE 1: SELECT id FROM E'positions_statusrecord' WHERE "type"=E'Leav...

Voici la requête brute je suis en train d'utiliser (c'est une méthode de gestion):

def get_status_ids(self, model): 
    """ 
    This query returns the latest statuses ids for each entry 
    of "model" in StatusRecord. 
    """ 
    db_table = self.model._meta.db_table 
    model_type = model.get_status_type() 

    raw_query = (
     "SELECT id " 
     "FROM %s " 
     "WHERE \"type\"=%s AND " 
     "(identifier,date_time) IN " 
       "(" 
          "SELECT identifier, Max(date_time) " 
          "FROM %s " 
          "WHERE \"type\"=%s " 
          "GROUP BY identifier" 
       ")" 
    ) 

    params = (db_table, model_type, db_table, model_type,) 
    return self.raw(raw_query, params) 

J'ai essayé avec une requête simple (juste un SELECT ... FROM ..) et a eu le même problème. Il semble que les requêtes brutes ne puissent pas avoir la partie FROM complétée avec un paramètre.

Ai-je raison? ou ai-je fait une erreur et je ne le trouve pas? J'utilise postgreSQL 8.4.10, django 1.3 et python 2.6.

J'ai cherché des informations sur les paramètres de requêtes brutes pour voir s'il y a des options de formatage interdites, mais je n'ai rien trouvé qui m'aide.

Est-ce que quelqu'un sait ce qui cause cette erreur?

Répondre

2

It seems to be that raw queries couldn't have the "FROM" part completed with a parameter.

Oui, l'ORM va citer l'argument de chaîne qui en fait ... FROM 'some_table' ....

Depuis le paramètre db_table est approuvé (ne proviennent pas de l'entrée de l'utilisateur), vous pouvez faire quelque chose comme:

raw_query = (
    "SELECT id " 
    "FROM %s " 
    "WHERE \"type\"=%%s AND " 
    "(identifier,date_time) IN " 
      "(" 
         "SELECT identifier, Max(date_time) " 
         "FROM %s " 
         "WHERE \"type\"=%%s " 
         "GROUP BY identifier" 
      ")" 
) % (db_table, db_table) 
return self.raw(raw_query, (model_type, model_type)) 

Depuis Django Aggregation can be used in filters, probablement vous pouvez obtenir les mêmes résultats sans avoir recours à SQL brut (regardez aussi le in lookup example).

Regardez si vous pouvez remplacer raw() avec QuerySet.extra() et SQL IN avec EXISTS.

+0

Nous vous remercions de votre réponse rapide! Je pensais qu'il était toujours recommandé de passer des arguments aux requêtes brutes dans l'argument "params". Je suis un débutant dans les questions de sécurité, donc j'ai essayé de l'utiliser toujours de cette façon. Mais c'est vrai que c'est une entrée de confiance dans ce cas. A propos du problème "EXISTS", je pense que je l'ai fait avant, mais d'une autre manière, et j'ai eu quelques problèmes de performance. Si j'ai raison, cette requête ferait une sous-requête pour chaque entrée de la table et la table contient beaucoup d'entrées (plus de 2000). Bien que je pense que j'avais fait cela, je voudrais essayer à nouveau. Merci beaucoup! – marianobianchi

+0

@marianobianchi: 2000 entrées est assez petit, vous ne pouvez voir aucune différence entre 'IN' et' EXISTS'. –