1

Dans mon projet django, je travaille avec une base de données héritée, qui comporte une table avec plusieurs clés primaires. Je suis confronté au problème où Django ORM construit incorrectement des requêtes SQL lorsque j'appelle la méthode save() sur une instance de modèle.Plusieurs clés primaires dans un projet django avec une base de données existante

Par exemple, j'ai le modèle suivant:

class MyTable(models.Model): 
    field_1 = models.IntegerField(primary_key=True) 
    field_2 = models.BooleanField(default=False, null=False) 
    field_3 = models.BooleanField(default=False, null=False) 
    user = models.ForeignKey(
     CustomUser, models.DO_NOTHING, db_column='userid', primary_key=True) 

    class Meta: 
     managed = False 
     db_table = 'my_table' 
     unique_together = (('user', 'field_1'),) 

je reçois l'exemple du modèle comme ça: mytable_instance = MyTable.objects.all()[0]. Ensuite, je veux modifier cette instance:

mytable_instance.field_2 = True 
mytable_instance.field_2.save() 

Cependant, Django ORM exécute cette requête:

{'sql': 'UPDATE `my_table` SET `field_2` = 1, `field_3` = 0 WHERE `my_table`.`field_1` = 123', 'time': '0.000'} 

ce qui est inexact, car il établira de nouvelles valeurs pour field_2 et field_3 pour toutes les lignes my_table avec field_1 = 123

Comment puis-je résoudre ce problème? J'ai besoin d'une requête SQL comme ceci:

'UPDATE `my_table` SET `field_2` = 1, `field_3` = 0 WHERE `my_table`.`field_1` = 123 AND `my_table`.`user_id` = 1' 

EDIT: code complet

Modèle pour la table de base de données existante:

class MyTable(models.Model): 
    field1_id = models.IntegerField(db_column='field1id', primary_key=True) 
    is_favorite = models.BooleanField(db_column='isfavorite', default=False, null=False) 
    is_admin = models.BooleanField(db_column='isadmin', default=False, null=False) 
    role = models.IntegerField(default=USER_GUEST, null=False) 
    field2 = models.BooleanField(null=False, default=True) 
    field3 = models.BooleanField(null=False, default=True) 
    is_active = models.BooleanField(db_column='isactive', null=False, default=True) 

    user = models.ForeignKey(
     CustomUser, models.DO_NOTHING, db_column='userid', primary_key=True) 

    DB_NAME = 'default' 

    class Meta: 
     managed = False 
     db_table = 'mytable' 
     unique_together = (('user', 'field1_id'),) 

Requêtes:

>>> from web_services.apps.my_app.models import MyTable 
>>> g = MyTable.objects.get(field1_id=12) 
>>> g.is_active = True 
>>> g.save() 
>>> connection.queries[-1] 
{'time': '0.000', 'sql': 'UPDATE `mytable` SET `isfavorite` = 0, `isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 WHERE `mytable`.`field1id` = 12'} 

Mais j'ai besoin :

{'time': '0.000', 'sql': 'UPDATE `mytable` SET `isfavorite` = 0, `isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 WHERE `mytable`.`field1id` = 12' AND `mytable`.`userid` = 1'} 
+0

Ce n'est guère plausible. Veuillez poster votre code complet, je suppose qu'il y a un problème dans votre code qui mène à cela. – e4c5

+0

@ e4c5 J'ai ajouté la mise à jour ci-dessus, merci! – AmirM

Répondre

1

Let regard à ces deux requêtes:

UPDATE `mytable` 
SET `isfavorite` = 0, `isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 
WHERE `mytable`.`field1id` = 12 

Et

UPDATE `mytable` 
SET `isfavorite` = 0,`isadmin` = 1, `role` = 3, `field2` = 1, `field3` = 1, `isactive` = 1 
WHERE `mytable`.`field1id` = 12' AND `mytable`.`userid` = 1 

La seule différence entre les deux est le bit AND userid=1.

Il est en effet correct quand vous dites que

il établira de nouvelles valeurs pour Champ_2 et field_3 pour toutes les lignes my_table avec field1_id = 12

Il y a exactement une telle ligne. Pourquoi? car vous avez défini field_id comme clé primaire. Ce qui garantit qu'il n'y a qu'une et une seule ligne avec field1_id = N où N est un entier.

La requête django se comporte donc parfaitement.

+0

Le problème, que c'est une base de données héritée, et il a ces combinaisons possibles de '(field1_id, user)': '(12, 1)', '(12,2)', '(12, 3)', ' (2, 1) ',' (3, 1) 'et etc. Donc, avec' 'mytable'.'field1id' = 12' il met à jour tout '(12, 1)', '(12,2)', '(12, 3)' – AmirM

+0

Donc, ma question devrait probablement être comment définir la clé composite? – AmirM

+0

Non, pas selon le modèle que vous avez posté. Il n'y a pas ** (12, 1), (12,2), (12, 3) ** – e4c5