2009-07-23 7 views
1

J'ai simple la requête de django définir comme:Jeu de requêtes django en double?

qs = AModel.objects.exclude(state="F").order_by("order") 

Je voudrais l'utiliser comme suit:

qs[0:3].update(state='F') 
expected = qs[3] # throws error here 

Mais la dernière déclaration jette: « Impossible de mettre à jour une requête une fois par tranche a été pris."

Comment puis-je dupliquer l'ensemble de requêtes?

Répondre

2

C'est la première ligne à lancer l'erreur: vous ne pouvez pas faire qs [0: 3] .update(). qs [0: 3] prend une tranche; update() met à jour la requête.

mise à jour() est destiné à des mises à jour en vrac, ce qui dans les requêtes SQL comme

UPDATE app_model SET state = 'F' WHERE state <> 'F'; 

Vous essayez de mettre à jour les trois premiers éléments selon « l'ordre », mais qui ne peut être fait avec cette type de UPDATE - vous ne pouvez pas commander ou limiter un SQL UPDATE. Il doit être écrit différemment, par exemple.

UPDATE app_model SET state = 'F' WHERE id IN (
    SELECT id FROM app_model WHERE state <> 'F' ORDER BY order LIMIT 3 
) AS sub; 

mais Django ne peut pas le faire pour vous.

0

Il y a eu des discussions sur la possibilité de faire des tranches d'un jeu de requête et de pouvoir ensuite les mettre à jour avant, mais AFAIK n'a jamais rien fait. Je ne pense pas que vous pouvez copier une tranche d'un jeu de requête, mais dans ce cas, vous n'aurez pas besoin de le faire. Si votre commande est un entier unique, vous seriez en mesure de le faire:

qs = AModel.objects.exclude(state="F").order_by("order") 
if len(qs) > 3: 
    slice = qs.exclude(order__gt=qs[3]) 
else: 
    slice = qs 
slice.update(state='F') 

J'utilise exclure pour éliminer les éléments indésirables, mais cela ne fonctionnera que si l'ordre est unique, sinon vous ne serez pas en mesure de savoir combien vous mettez à jour. Pour de cas n'est pas unique, il sera toujours possible à l'aide d'une seconde et arg unique afin:

qs = AModel.objects.exclude(state="F").order_by("order", "pk") 
if len(qs) > 3: 
    slice = qs.exclude(order__gt=qs[3]).exclude(order=qs[3], pk__gt=qs[3]) 
... 
+0

Notez que ceci est nonatomic, même dans une transaction (au moins dans Postgres), sauf si vous enlevez d'abord un verrou de table. –

+0

Vous pouvez copier un jeu de requête avec qs.all(), mais cela ne vous aidera pas ici. –

+0

Je voulais dire copier une partie d'un QuerySet pour en créer un nouveau sur lequel vous pouvez exécuter la mise à jour. Réponse clarifiée – googletorp

1

Vous pouvez faire ceci:

qs = AModel.objects.filter(id__in= AModel.objects.exclude(state="F").order_by("order")[10]).update()

Questions connexes