2014-06-08 65 views
1

我想要做的是一個數據庫來跟蹤個人記錄。 模型幾乎完成,但我面臨一些困難,以存儲不同類型的記錄。Django模型的可變類型的數據

有時間記錄,體重,對於重複/圈,距離......所以,有diferent類型的數據:時間,十進制整數...

起初,我創建了一個表(或django類)爲每種類型的數據。時間表,其他重量(小數)等等。

但我不知道是否有更好的解決方案,只保留一個表的所有記錄。

我給分離表/模型(所以,我有對於每種類型的一個類,共5個)代碼:(此效果很好,但我必須預先選擇apropriate模型中插入數據)

class PRWeight(model.Models): # there are PRDistance, PRLaps, PRHeight, PRTime 
    user = FK(User) 
    exercise = FK(Exercise) 
    date = datefield() 
    weight = decimalfield() # integer, integer, decimal, time 

    class Meta: 
     unique_together = [user, exercise, date,] 

或者,我可以做這樣的事情,如果它是一個好或有更好的解決方案:

class PR(models.Model): 
    user = FK(User) 
    exercise = FK(Exercise) 
    date = datefield() 
    metric = FK(Metric) # choose between time, weight, height... 
         # the aspect beeing mesured 
    record =    # how can I call the right field type? 

或者我可以repalce與空白等五大領域領域的「記錄」 =真

class PR(models.Model): 
    user = FK(User) 
    exercise = FK(Exercise) 
    date = datefield() 
    metric = FK(Metric) # choose between time, weight, height, distance... 
         # the aspect beeing mesured 
         # not necessary in this approach 
    wheight = decimalfield(blank=True) 
    height = decimalfield(blank=True) 
    time = timefield(blank=True) 
    distance = integerfield(blank=True) 
    laps = integerfield(blank=True) 

我正在尋找一個簡單的解決方案。到目前爲止,我傾向於選擇最後一個示例,因爲它很簡單,但填寫表單的用戶可能會犯錯誤...

+0

創建一個抽象模型存放所有類似的數據,然後單獨你的每個模型的具體數據到它的每一個。 您可以使用Abastract模型或表繼承,這取決於您的應用程序邏輯來定義哪個是最好的方法。 – petkostas

+0

我不認爲你應該擔心表格,除非你直接進入數據庫。 Django具有非常好的ORM,ORM的主要方面是,您不必查看數據庫以及它如何存儲。只需創建一個漂亮的類層次結構來訪問所有項目和模型,並讓O​​RM決定需要多少表來保存它們。 –

回答

1

一個表包含生成某些語句的行(參數化爲列名)true。只要您可以使用它們製作單個語句,表格就應該只有列。

使很多,但相關的列在一起

如果(用戶,運動,日期),總是有一個重量和日期,有一個表。

-- user [user] in exercise [exercise] on [date] weighed [weight] kg and was [height] m tall 
PRstuff(user,exercise,date,weight,height) 

但是,如果(用戶,運動,日期)可能有一個權重,但不是日期,有單獨的表。

-- user [user] in exercise [exercise] on [date] lifted [weight] kg 
PRlift(user,exercise,date,weight) 
-- User [user] in exercise [exercise] on [date] jumped [height] m 
PRjump(user,exercise,date,height) 

條件列複雜

很可能有一個說法/表像你的第三個例子:

--  user [user] did [exercise] on [date] 
-- AND (lifted != blank and they lifted [weight] kg OR lifted = blank and they didn't lift) 
-- AND (jumped != blank and they jumped [height] m OR jumped = blank and they didn't jump) 
PR(user,exercise,date,weight,height) 

但你可以看到你的查詢語句,這是組合的表格語句,以及作爲表格組合的SQL表達式變得複雜。基本上,在查詢時你必須不斷地將這個表格切換成單獨的非條件表格版本。

不要使用記錄類型的列

有時候,我們可以有一個類型是由固定部分的一列。但是如果你想用像SQL那樣的邏輯條件來查詢部件,那麼你應該把部件製成表格的列。

-- user [user] in exercise [exercise] on [date] weighed [record.weight] kg and was [record.height] m tall 
PRrecord(user,exercise,date,record) 

SELECT * FROM PRrecord 
WHERE PRrecord.record.weight = 100 -- really, record_dot(PRrecord.record,'weight')=100 

這裏第一個點是數據庫表操作,但第二個點是編程語言記錄操作。 DBMS無法優化您的查詢,因爲它優化了表操作,而不是數據類型操作。基本上它必須得到一大堆行,而不是查看記錄值,然後調用記錄運算符點,然後調用字段相等,然後丟掉很多行。

SELECT * FROM PR 
WHERE PR.weight = 100 

現在,DBMS可以將字段相等性組合成優化獲取行的方式,因爲您只使用了表格版本的點。

不要使用容器類型的列

有時候,我們可以有一個類型是由類似零件的集合列。但是如果你想用像SQL那樣的邏輯條件查詢部件,那麼你應該創建一個新表。新表具有該特定集合的PK列,而舊錶具有對新PK的FK列。

-- user [user] in exercise [exercise] on [date] and their set of lifted weights in kg is [weights] 
PRlifts(user,exercise,date,weights) 

SELECT user FROM PRlifts l 
WHERE l.name = 'Fred' AND set_has_member(l.weights,200) 
AND ??? no two lifts were the same weight ??? 

不好。注意聲明如何複雜。另外,DBMS不能優化查詢,因爲set_has_member不是表操作。更糟的是,你甚至無法查詢某些條件,你必須編寫非查詢循環代碼。

SELECT user FROM PRlift l 
WHERE l.user = 'Fred' AND l.weight = 200 
AND NOT EXISTS(
    SELECT weight 
    FROM Prlift l1, PRlift l2 
    WHERE l1.user = l.user AND l2.user = l.user AND l1.weight = l2.weight 
) 

現在DBMS可以優化並消除循環。

(請注意,如果這是

WHERE string_length(l1.name) = string_length(l2.name) 

則DBMS可以進一步優化通過具有名稱長度列,但通常是一個數據庫管理系統具有字符串和某些其它類型和或多或少優化了特殊的知識,就好像某些列存在對應於特定運營商的值。其實一個DBMS能知道有關記錄和集合類型,但你仍然不能有簡單的報表和查詢looplessly。)