Django sinyalleri ve geçersiz kılma kaydetme yöntemi


89

Kafamı bunun etrafına dolamakta zorlanıyorum. Şu anda şuna benzeyen bazı modellere sahibim:

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

Bir İncelemenin birkaç "puanı" vardır, genel_skor puanların ortalamasıdır. Bir inceleme veya puan kaydedildiğinde, genel_ puan ortalamasını yeniden hesaplamam gerekir. Şu anda geçersiz kılınmış bir kaydetme yöntemi kullanıyorum. Django'nun sinyal dağıtıcısını kullanmanın herhangi bir faydası olur mu?

Yanıtlar:


85

Kaydetme / silme sinyalleri, söz konusu modele tamamen özel olmayan değişiklikler yapmanız gereken veya ortak bir şeye sahip olan veya modellerde kullanılmak üzere yapılandırılabilen modellere uygulanabilecek durumlarda genellikle uygundur.

Geçersiz kılınan saveyöntemlerde yaygın bir görev , bir modeldeki bazı metin alanlarından otomatik olarak sümüklü böcek üretmektir. Bu, bir dizi model için uygulamanız gerekirse pre_save, sinyal işleyicinin bilgi bilgisini oluşturmak için bilgi alanı adını ve alanın adını alabileceği bir sinyal kullanmaktan fayda sağlayacak bir şeye örnek . Böyle bir şeyi yerine getirdikten sonra, yerleştirdiğiniz gelişmiş işlevler de tüm modeller için geçerli olacaktır - örneğin, benzersizliği sağlamak için, söz konusu model türü için eklemek üzere olduğunuz kurguya bakmak.

Yeniden kullanılabilir uygulamalar genellikle sinyal kullanımından yararlanır - sağladıkları işlevsellik herhangi bir modele uygulanabiliyorsa, genellikle (kaçınılmaz olmadığı sürece) kullanıcıların bundan yararlanmak için modellerini doğrudan değiştirmesini istemezler.

Örneğin django-mptt ile , pre_savesinyali, oluşturulmak veya güncellenmek üzere olan model için bir ağaç yapısını ve pre_deletesilinen nesne ve tümünün ağaç yapısı ayrıntılarını kaldırmak için bir alan kümesini yönetmek için kullandım. kendisinden önceki nesnelerin alt ağacı ve silinirler. Sinyallerin kullanımından dolayı, kullanıcılar bu yönetimi kendileri için yaptırmak için modellerine yöntem saveveya deleteyöntem eklemek veya değiştirmek zorunda kalmazlar, sadece django-mptt'nin hangi modelleri yönetmesini istediklerini bilmesini sağlamaları gerekir.


Ya sinyal işleyici bir istisnayı tetiklerse? Sanırım istisnaları tetiklememeliler, yoksa uygun değiller. Yanlış mıyım?
x-yuri

20

Sen sordun:

Django'nun sinyal dağıtıcısını kullanmanın herhangi bir faydası olur mu?

Bunu django belgelerinde buldum:

Geçersiz kılınan model yöntemleri toplu işlemlerde çağrılmaz

Bir nesnenin delete () yönteminin, bir QuerySet kullanılarak nesneleri toplu olarak silerken veya bir basamaklı silme sonucunda çağrılması gerekmediğini unutmayın. Özelleştirilmiş silme mantığının yürütülmesini sağlamak için pre_delete ve / veya post_delete sinyallerini kullanabilirsiniz.

Kaydet (), pre_save ve post_save işlevlerinin hiçbiri çağrılmadığından ne yazık ki nesneleri toplu olarak oluştururken veya güncellerken bir çözüm yoktur.

Kimden: Önceden tanımlanmış model yöntemlerini geçersiz kılma


3
Django yönetici listesi görünümü toplu silme kullanıyor ... bu haberle karşılaşana kadar kafası karışmıştı.
N.Balauro

8
ayrıca "Ne yazık ki, nesneleri toplu olarak oluştururken veya güncellerken bir çözüm yoktur, çünkü save (), pre_save ve post_save çağrılmamaktadır." - bu yüzden bu yöntemler arasında bir değiş tokuş olduğunu düşünmüyorum.
Cory

Bu her iki yöntem için de geçerlidir, o zaman cevap şu şekildedir: "hayır, saveyöntemi geçersiz kılmak yerine sinyalleri kullanmanın bir faydası yoktur "?
Flimm

3

Sinyalleri kullanacaksanız, ilgili puan modeli her kaydedildiğinde İnceleme puanını güncelleyebilirsiniz. Ancak böyle bir işlevselliğe ihtiyacım yoksa, bunu sinyale sokmak için herhangi bir neden görmüyorum, bunlar oldukça modelle ilgili şeyler.



1

Django belgelerinden toplu silme hakkında küçük ekleme ( nesneler .delete()üzerinde yöntem QuerySet):

Bunun mümkün olduğunda tamamen SQL'de yürütüleceğini ve bu nedenle tek tek nesne örneklerinin delete () yöntemlerinin işlem sırasında mutlaka çağrılmayacağını unutmayın. Bir model sınıfında özel bir delete () yöntemi sağladıysanız ve çağrıldığından emin olmak istiyorsanız, bu modelin örneklerini "manuel olarak" silmeniz gerekir (örneğin, bir QuerySet üzerinde yineleyerek ve delete () öğesini çağırarak QuerySet'in toplu delete () yöntemini kullanmak yerine her nesneyi ayrı ayrı).

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

Ve toplu güncelleme ( nesneler .update()üzerinde yöntem QuerySet):

Son olarak, update () 'in SQL düzeyinde bir güncelleme yaptığını ve bu nedenle modellerinizde herhangi bir save () yöntemini çağırmadığını ve pre_save veya post_save sinyallerini (Model.save (Model.save () çağırmanın bir sonucu olan )). Özel bir save () yöntemi olan bir model için bir grup kaydı güncellemek istiyorsanız, bunların üzerinde döngü yapın ve save () öğesini çağırın

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update


Bu her ikisi için de geçerli değil mi?
Flimm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.