2009-03-07 17 views
16

Mam tabeli z IntegerField (hit_count), a gdy strona jest odwiedzana (np http://site/page/3) Chcę rekord ID 3 za hit_count kolumna w bazie danych, aby zwiększyć o 1.Przyrost strony Hit Count w Django

zapytanie powinno być tak:

update table set hit_count = hit_count + 1 where id = 3 

mogę to zrobić ze standardowymi konwencjami Django model? A może powinienem napisać zapytanie ręcznie?

+0

Pomaga, jeśli podasz sam model. –

+0

Możliwy duplikat [przyrostu atomowego licznika w django] (http://stackoverflow.com/questions/1598932/atomic-increment-of-a-counter-in-django) –

Odpowiedz

31

Jeśli używasz Django 1.1+, wystarczy użyć F expressions:

from django.db.models import F 
... 
MyModel.objects.filter(id=...).update(hit_count=F('hit_count')+1) 

ten wykona jedną kwerendę bazy atomowej.

Gerdemb mówi, że powinieneś rozważyć umieszczenie tego w oprogramowaniu pośredniczącym, aby można je było łatwo ponownie wykorzystać, aby nie zaśmiecało wszystkich widoków.


+1

+1: http://docs.djangoproject.com/en/dev/topics/db/queries/#filters-can-reference-fields-on-the-model –

+0

Dzięki - ma na celu połączenie z tym, ale zapomniałem. Dodam to. –

+1

Myślę, że chcesz 'MyModel.objects.get (id = ...)' w przeciwieństwie do 'filter'; jeśli wiemy, że jest to pojedynczy wiersz, dlaczego nie wyjaśnić? –

0

Konwencje modelowe nie będą atomowe; napisać go ręcznie:

BEGIN 
SELECT * FROM table WHERE id=3 FOR UPDATE 
UPDATE table SET hit_count=hit_count+1 WHERE id=3 
COMMIT 
+1

ORM Django ma wsparcie dla tego zapytania (w tułów, a wkrótce v1.1) - nie trzeba pisać ręcznie. –

0

chciałbym zacząć patrząc na dokumentacji middleware. Komentarz Ignacio o braku transakcji atomowych jest prawdziwy, ale jest to problem z całą strukturą Django. Jeśli nie martwisz się o to, że masz 100% dokładny licznik, nie martwię się o to.

+0

Jak to jest "problemem z całą strukturą Django?" Możesz mieć transakcję atomową na żądanie za pomocą TransactionMiddleware lub uzyskać precyzyjniejsze sterowanie za pomocą funkcji w django.db.transaction. –

+0

Na pewno możesz mieć transakcje, ale nie są one domyślnie włączone. Jeśli zbudujesz prostą aplikację CRUD przy użyciu wbudowanego administratora Django, będziesz miał warunki wyścigowe. Nawet samouczek w dokumentacji Django ma tego rodzaju problemy. – user27478

+0

Sposób, w jaki to sformułowałeś, sprawia, że ​​brzmi to jak nieunikniony problem, który jest oczywiście mylący dla kogoś, kto może nie wiedzieć tak dużo o Django jak ty. – Jordan

4

Jak mówi gerdemb, powinieneś zapisać go w oprogramowaniu pośredniczącym, aby był naprawdę przydatny do ponownego użycia. Lub (prościej) napisz dekorator funkcji. W rzeczywistości istnieją adaptery do używania oprogramowania pośredniego jako dekoratora i viceversa.

Ale jeśli martwisz się wydajnością i chcesz, aby zapytania DB na stronę były niskie, możesz użyć operacji atomowej przyrostu memcached. oczywiście w tym przypadku sam musisz zadbać o upór.

+0

Dla dobrej wydajności rozwiązanie memcached jest zdecydowanie najlepsze, ale jest bardziej skomplikowane. –