2009-03-07 27 views
16

Bir IntegerField (hit_count) içeren bir tablo var ve bir sayfa ziyaret edildiğinde (örneğin, http://site/page/3) sorgu gibi olmalıdır Django'da Artış Sayfa Sayısı

kayıt kimlik veritabanında 3'ün hit_count sütun 1.

tarafından artırmak istediğiniz:

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

Bu standart Django Model sözleşmeleri ile yapabilir misin? Ya da sadece elle sorgu yazmalıyım?

+0

Modelin kendisini sağlamanız yardımcı olur. –

+0

Olası kopyası [django'da sayacın atomik artışı] (http://stackoverflow.com/questions/1598932/atomic-increment-of-a-counter-in-django) –

cevap

31

, sadece F expressions kullanın:

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

Bu, tek atom veritabanı sorgusu gerçekleştirecektir.

Gerdemb'in dediği gibi, bunu kolayca yeniden kullanılabilir hale getirmek için bir ara katmana koymayı düşünmelisiniz, böylece tüm görünümlerinizi karıştırmaz.


+1

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

+0

Teşekkürler - bununla bağlantı kurmayı unutmuşum. Ekleyeceğim. –

+1

İstediğimi sandığım 'filter' karşıt olarak MyModel.objects.get (id = ...) '; Tek bir satır olduğunu biliyorsak, neden açıklığa kavuşturmuyoruz? –

0

Model kuralları atomik olmayacak; elle yazmak: Ben middleware belgelerine bakarak başlayacaktı

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

Django'nun ORM'si bu sorguyu destekler. trunk, ve yakında v1.1) - elle yazmanıza gerek yok. –

0

. Ignacio'nun atomik işlemlerin eksikliğiyle ilgili yorumu doğrudur, ancak bu tüm Django çerçevesiyle ilgili bir sorundur. % 100 doğru bir sayaç sahibi olmayla ilgili endişeleriniz yoksa, endişelenmeyeceğim.

+0

Bu "Django çerçevesinin tamamı ile ilgili sorun nedir?" TransactionMiddleware ile istek başına atomik işleminiz olabilir veya django.db.transaction'daki işlevlerle daha hassas denetim yapabilirsiniz. –

+0

Elbette işlemlerin olabileceğini, ancak varsayılan olarak etkin olmadıklarını unutmayın. Yerleşik Django yöneticisini kullanarak basit bir CRUD uygulaması oluşturursanız, yarış koşullarına sahip olacaksınız. Django belgelerindeki öğretici bile bu tür sorunlara sahiptir. – user27478

+0

Kastettiğiniz şey, kaçınılmaz bir problem gibi görünmesini sağlar, tabi ki sizin gibi Django hakkında bilmeyen birisine yanıltıcıdır. – Jordan

4

Gerdemb'in dediği gibi, onu gerçekten yeniden kullanılabilir hale getirmek için bir ara katmana yazmalısınız. Veya (daha basit) bir işlev dekoratörü yazın. Aslında, bir ara katmanını bir dekoratör ve viceversa olarak kullanacak adaptörler vardır.

Ancak, performans konusunda endişeleriniz varsa ve sayfa başına DB sorgularını düşük tutmak istiyorsanız, memcached'ın atomik artış işlemini kullanabilirsiniz. Tabii ki, bu durumda, kendinize kalıcılık göstermelisiniz. Django 1.1+ kullanıyorsanız

+0

İyi bir performans için, memcached çözümü en iyisi olmakla birlikte, daha karmaşıktır. –