2009-11-27 26 views
2

我不知道這是否是解決我的問題的最好辦法,如果不是,告訴我PLZ :)Django的 - 添加在線列在「選擇」

我有這樣的模式:


class userTrophy(models.Model): 
user  = models.ForeignKey(userInfo) 
platinum = models.IntegerField() 
gold = models.IntegerField() 
silver = models.IntegerField() 
bronze = models.IntegerField() 
level = models.IntegerField() 
perc_level = models.IntegerField() 
date_update = models.DateField(default=datetime.now, blank=True) 

現在我想獲取一個用戶的信息,但我想添加3個新的「列」在線:

總=白金+黃金+銀+青銅

點=鉑* 100 +金* 50 +銀* 25 +青銅* 10

並按「點」進行排序,排序後,放入一個新的列,序號爲:rank(1-n)。

我可以做這個(或其中的一部分)只與模型一起工作嗎?

回答

3

我相信有很多方法可以實現這種行爲。我現在想到的是Custom Model Manager和瞬態模型領域。

你的類可能看起來像這樣:

from django.db import models 
from datetime import datetime 

class UserTrophyManager(models.Manager): 
    def get_query_set(self): 
    query_set = super(UserTrophyManager, self).get_query_set() 

    for ut in query_set: 
     ut.total = ut.platinum + ut.gold + ut.silver + ut.bronze 
     ut.points = ut.platinum * 100 + ut.gold * 50 + ut.silver * 25 + ut.bronze * 10 

    return query_set 

class UserTrophy(models.Model): 
    user   = models.CharField(max_length=30) 
    platinum  = models.IntegerField() 
    gold   = models.IntegerField() 
    silver  = models.IntegerField() 
    bronze  = models.IntegerField() 
    level  = models.IntegerField() 
    perc_level = models.IntegerField() 
    date_update = models.DateField(default=datetime.now, blank=True) 

    total  = 0 
    point  = 0 

    objects  = UserTrophyManager() 

    class Meta: 
    ordering = ['points'] 

所以,你可以用下面的,並得到全面和點計算:

user_trophies = userTrophy.objects.all() 

for user_trophy in user_trophies: 
    print user_trophy.total 
+0

什麼是「瞬態模型場」? – 2009-11-27 19:25:38

+1

一般來說,模型中有兩種類型的字段。持久性字段和瞬態字段。持久性字段由數據庫字段表示,而瞬態字段只在對象所在的時間內存在。這意味着瞬態場只是暫時的。這不是一個「Django術語」。這是這類領域的一個通用術語。 – Jens 2009-11-27 20:05:39

+0

在你的例子中,總分和分數是類屬性。 Django元類是否對它們做了一些特殊的處理,將它們變成實例級屬性? – 2009-11-27 20:15:53

1

這比回答的後續問題,但是否有可能做這樣的事情:

class userTrophy(models.Model): 
... stuff... 

    def points(self): 
     self.gold + self.silver + self.bronze 

然後調用類似object.points在一個模板。林只是好奇,如果這是一種可能性

+0

當然有可能,Django模型只是Python類,你可以定義你喜歡的任何方法。 – 2009-11-27 19:20:00

+0

定義這種方法的缺點是ORM不能在查詢中使用它。 – 2009-11-27 20:58:32

3

這是我會做到這一點。列「總」和「點」添加到你的模型,像這樣:

class UserTrophy(models.Model): 
    ... 
    total = models.IntegerField() 
    points = models.IntegerField() 
    ... 

覆蓋保存方法模型:

def save(self, *args, **kwargs): 
    # Compute the total and points before saving 
    self.total = self.platinum + self.gold + self.silver + self.bronze 
    self.points = self.platinum * 100 + self.gold * 50 + \ 
     self.silver * 25 + self.bronze * 10 

    # Now save the object by calling the super class 
    super(UserTrophy, self).save(*args, **kwargs) 

總與點作爲一等公民在您的模型,你的「等級」概念就成爲對UserTrophy對象進行排序和切片的問題。

top_ten = UserTrophy.objects.order_by('-points')[:10] 

您還需要確保您的字段已編入索引,因此您的查詢效率很高。

如果您不喜歡將這些字段放入您的模型的想法,您可以使用Django查詢集對象的extra功能來計算您的總和和即時點。我不經常使用它,所以也許別人可以舉一個例子。

此外,我建議您閱讀PEP 8 Python編碼約定。

+0

看起來像一個很好的方式來做到這一點!也許這是更好的方法,因爲你只做一次計算值,而不是每次加載對象! – Jens 2009-11-27 19:27:21

+0

需要注意的一個缺點是,如果你在Django ORM之外更新你的表格,你必須記住保持你的點數和總體更新。 – 2009-11-27 19:30:45

+0

感謝您的回答! 只是一個問題,爲什麼我需要閱讀PEP 8?我在代碼上犯了一些樣式錯誤? – fabriciols 2009-11-30 14:42:23