2009-11-07 69 views
1

考慮車型:Django的:他們的孩子的屬性訂貨對象

class Author(models.Model): 
    name = models.CharField(max_length=200, unique=True) 

class Book(models.Model): 
    pub_date = models.DateTimeField() 
    author = models.ForeignKey(Author) 

現在假設我要訂購所有的書,比方說,他們PUB_DATE。我會用order_by('pub_date')。但是,如果我想根據最近出版的書籍排列所有作者的列表,該怎麼辦?

當你考慮它時,它確實非常簡單。它本質上是:

  • 在頂部的作者是誰最近出版了一本書
  • 下一個是誰出版的書並不像新的一樣第一個的人,
  • 於是就等

我可能會一起破解一些東西,但由於這可能會變得很大,我需要知道我做得對。

幫助感謝!

編輯:最後,是否可以選擇只添加一個新字段來顯示上一本書的日期,只是更新整個時間會更好?

回答

1

最後,只是增加一個會的選項。每個人都有新的領域來顯示上一本書的日期,並且只是更新整個時間會更好?

其實它會!這是一個正常的非規範化的做法,可以這樣進行:

class Author(models.Model): 
    name = models.CharField(max_length=200, unique=True) 
    latest_pub_date = models.DateTimeField(null=True, blank=True) 

    def update_pub_date(self): 
     try: 
      self.latest_pub_date = self.book_set.order_by('-pub_date')[0] 
      self.save() 
     except IndexError: 
      pass # no books yet! 

class Book(models.Model): 
    pub_date = models.DateTimeField() 
    author = models.ForeignKey(Author) 

    def save(self, **kwargs): 
     super(Book, self).save(**kwargs) 
     self.author.update_pub_date() 

    def delete(self): 
     super(Book, self).delete() 
     self.author.update_pub_date() 

這是你有除了兩個第三常見的選擇已經建議:

  • 與加盟做在SQL和分組
  • 將所有書籍都放到Python端並刪除重複項

這兩個選項都選擇在讀取t時從規範化數據計算pub_dates下襬。非正規化在您編寫新數據時爲每位作者執行此計算。這個想法是,大多數網絡應用的讀取次數通常比寫入次數多,所以這種方法更可取。

一個這種感知缺點的是,基本上你在不同的地方相同的數據,它需要你保持同步。它通常使數據庫人員感到恐懼:-)。但是,直到你使用你的ORM模型來處理dat(你可能會這樣做),這通常不是問題。在Django中,它是控制數據庫的應用程序,而不是其他方式。

另一個(更現實)的缺點是,與我展示了大量的書籍更新可能是方法要慢天真的代碼,因爲他們平安作者更新每次更新他們的數據不管是什麼。這通常通過設置一個標誌來暫時禁用調用update_pub_date並在之後手動調用它來解決。基本上,非規範化數據需要比標準化更多的維護。

0
def remove_duplicates(seq): 
    seen = {} 
    result = [] 
    for item in seq: 
     if item in seen: continue 
     seen[item] = 1 
     result.append(item) 
    return result 


# Get the authors of the most recent books 
query_result = Books.objects.order_by('pub_date').values('author') 
# Strip the keys from the result set and remove duplicate authors 
recent_authors = remove_duplicates(query_result.values()) 
+0

嘿,看起來像我需要的東西。如果我可能會問: 1.它是如何工作的和 2.它在性能方面如何? – cwj 2009-11-07 07:51:28

+0

嗯其實對不起,我dn't hink這會工作,.distinct()調用將與列表交互,掛在我正準備給你。 – DevDevDev 2009-11-07 07:52:24

+0

有可能是一個更好的辦法,我能做到這一點的SQL,所以我知道你可以使用Django的模型做的,但我怎麼也想不到把我的頭頂部。 – DevDevDev 2009-11-07 07:58:57

1

或者,你可以玩的是這樣的:

Author.objects.filter(book__pub_date__isnull=False).order_by('-book__pub_date')

+0

不起作用,可能有許多書籍與作者相同。 – 2009-11-07 10:28:13

+0

我很抱歉,但爲什麼它不起作用,無論作者是否沒有書,一本書或更多? – ayaz 2009-11-07 18:19:34

1
from django.db.models import Max 
Author.objects.annotate(max_pub_date=Max('books__pub_date')).order_by('-max_pub_date') 

這需要您使用Django 1.1

,我以爲你會加上「related_name '到Book模型中的作者字段,因此它將由Author.books而不是Author.book_set調用。它更可讀。

0
上阿亞茲的解決方案

大廈,何談: Author.objects.filter(book__pub_date__isnull = FALSE).distinct()ORDER_BY( ' - book__pub_date')

相關問題