2012-10-01 133 views
1

我有一个问题。这两个属性会不同,我的意思是db命中。 例如,我们有模型的文章,具有ForeignKeybookdjango和模型的属性

from django.db import models 

class Article(models.Model): 
    book = models.ForeignKey("books.Book") 

是什么让一个author由prorerties的一个最好的办法:

@property 
def author(self): 
    if self.book: 
     return self.book.author 
    return None 

@property 
def author(self): 
    book = self.book 
    if book: 
     return book.author 
    return None 
+0

Django和蟒蛇明智的,这将是相等的。实际的命中是在你的queryset方法中。 – KillianDS

+0

我不确定我了解你的问题。你的两个选项看起来功能上与我完全相同。我会选择一个,因为它有一个较少的线。他们都需要2个查询:一个用于作者对象,另一个用于该书。但是,如果您使用select_related()选择作者对象,则可以将其作为一个参数,它将预先加入书本。 – acjay

回答

2

由于您正在定义Article上的属性,因此实际的数据库命中取决于如何检索Article查询集。如果在检索Article对象时在queryset上使用select_related([depth=2]),那么就数据库命中而言,这将是最优的,无论您如何编写属性。你列出的方式都有类似的表现。

+0

好的,我以为是,谢谢! –

0

您应该致电

article.book.author 

该调用将查询书籍对象并将其缓存在文章实例上。所以如果你在第一次调用之后调用article.book.id,它将不会运行第二个查询。

Personaly我认为你应该尽量避免在模型方法中碰到数据库。因为,随着应用程序变得复杂,开发人员只需调用文章的作者方法即使他们也拥有书本模型。因为两个属性实际上是相同的。

0

我喜欢这个选项,因为它使只有一个数据库查询:

@property 
def author(self): 
    authors = Author.objects.filter(book__article=self.id)[:1] 
    return authors[0] if authors else None 
+2

但是,无论是否使用'select_related',这种解决方案都会进行查询。 –

+0

是的,但有时候这是首选。而且,如果你确定在这个过程中'author'字段不会改变,你可以使用'@ memoized_property'而不是'@ property'。 – defuz

+0

@defuz有时不够好,举个具体的例子,当这可能是首选,有一个很好的理由。我看不到这个优点。 – KillianDS