2013-10-29 15 views
13

Django'da bir alandan, özellikle de çoktan bir ilişkinin "çok" bir parçasının, gerçekten getirmeden, prefetch_related() aracılığıyla getirilip getirilmediğini söylemesi için bir yol olup olmadığını mı merak ediyordum? (Django: İlgili alanın getirilmeden getirilip getirilmediğini anlatabilir misiniz?

class Question(Model): 
    """Class that represents a question.""" 

class Answer(Model): 
    """Class the represents an answer to a question.""" 
    question = ForeignKey('Question', related_name='answers') 

normalde bir soruya, aşağıdakileri yapmak olacak bu almanın en etkili yolu için cevapların sayısını almak için:

Yani, örnek olarak, bu reklam bu modelleri var diyelim cevaplar prefetch_related() çağrısı (veya bir şekilde aracılığıyla getirilmemiş bazı durumlarda Ancak

# Note: "question" is an instance of class Question. 
answer_count = question.answers.count() 

, daha önce yineledi ettiklerinden dolayı,: Django dokümanlar sadece bir sayım) gerekirse count() daha verimli olduğunu ifade çünkü cevap s). (Biz ekstra sayım sorgusu atlamak istiyorum çünkü) Böylece, bu tür durumlarda, bunu yapmak daha verimli olacaktır:

if question.answers_have_been_prefetched: # Does this exist? 
    answer_count = len(question.answers.all()) 
else: 
    answer_count = question.answers.count() 
:

# Answers were fetched via prefetch_related() 
answer_count = len(question.answers.all()) 

yüzden gerçekten ne yapmak istediğinizi gibi bir şey

Önemliyse Django 1.4 kullanıyorum. Şimdiden teşekkürler.

Düzenleme: prefetch_related()'un yanıtların alınmasının tek yolu olmadığını ekledi.

+0

burada sarıcı kütüphane kullanmanın bütün mesele 'don öyle mi Aslında, böyle şeyler hakkında endişelenmeliyim. Bunu gerçek bir darboğaz olarak ölçmediyseniz, sadece doğrudan yöntemi kullanın ve gereksiz karmaşıklık eklemeyin. Ancak, Django kaynak koduna biraz arandıktan sonra bazı ipuçları buldum. Eğer hala bu hack'i denemekte ısrar ediyorsanız, 'obj._prefetched_objects_cache' deneyebilirsiniz ya da alternatif olarak,' print dir (question.answers) 'seçeneğini deneyebilir ve orada herhangi bir önbellekle ilgili görünen parametreler görüp görmediğinizi görebilirsiniz. – kazagistar

+0

Devasa bir darboğaz değil, hayır. Sadece uygulamadan cehennemi gerçekten optimize etmeye ve sorgu sayısını minimum bir ayıya indirmeye çalışıyordum. Tek yol hacky ise, o zaman buna değmez. Açıklığa kavuşturmalıyım: prefetch_related sadece bir örnekti. Sonuçlar başka bir şekilde de getirilmiş olabilir (örneğin, daha önce soruları cevaplamak için). Bu yüzden genel bir çözüm bulmayı umuyorum. – Chad

+2

Django, önceden yüklenmiş ilişkilerin otomatik bellek içi filtrelemesini seçmenize izin verebilirse çok güzel olurdu, böylece zaten sahip olduğunuz verileri araştırmak için DSL'lerini kullanarak yeni bir sorgu oluşturmuyorsunuz. – skatenerd

cevap

20

Evet, Django, önceden oluşturulan sonuçların üst model örneğinin _prefetched_objects_cache özniteliğinde saklanmasını sağlar. gibi

Yani bir şey yapabilirsiniz:

instance = Parent.objects.prefetch_related('children').all()[0] 

try: 
    instance._prefetched_objects_cache[instance.children.prefetch_cache_name] 
    # Ok, it's pefetched 
    child_count = len(instance.children.all()) 
except (AttributeError, KeyError): 
    # Not prefetched 
    child_count = instance.children.count() 

v1.4.9 içinde Django kaynak bagajında ​​relevant use veya the equivalent Bkz

+0

Bunun için teşekkürler, ama açıklığa kavuşturmalıyım: prefetch_related sadece bir örnekti. Sonuçlar başka bir şekilde de getirilmiş olabilir (örneğin, daha önce koddaki soruların üstesinden gelmek). – Chad

+2

İlgili yönetici girişleri genellikle önbelleğe alınmaz, muhtemelen kendi not alma sarıcınızı uygulamanız gerekir: https://docs.djangoproject.com/en/dev/topics/db/optimization/#understand-queryset-evaluation –

+0

Ah, Tamam, bilmek güzel. Böylece, prefetch_related kullanıldığında sadece önbelleğe alınırlar. Açıklama için teşekkürler. Bu hack gibi çabalar çabaya değmez ve sadece saymalıyım(), ama bana ihtiyacım olan bilgiyi verdin. – Chad

İlgili konular