2012-12-11 71 views
1

使用Python/Flask/SQLAlchemy/Heroku。我可以將字典存儲爲對象的屬性嗎?

想要的對象字典存儲爲一個對象的屬性:

澄清

class SoccerPlayer(db.Model): 
    name = db.Column(db.String(80)) 
    goals_scored = db.Column(db.Integer()) 

^如何設置名稱和進球作爲一個字典?


更新:如果有任何區別,用戶將輸入名稱和goals_scored。

此外,我在網上尋找合適的答案,但作爲noob,我無法理解/實現我在Google上爲我的Flask網絡應用程序找到的內容。

+1

你在做什麼,你需要的數據結構是(理論上)'soccer_player.data [「name」],soccer_player.data [「goals_scored」]''而不是'soccer_player.name,soccer_player.goals_scored '? (知道這將有助於改善答案)。 –

+0

我想比較一支球隊的SoccerPlayer(s)列表與其他球隊的SoccerPlayer(s) - 根據進球得分。每個球隊得分最高的球員將被輸出到網頁。 – JoseBazBaz

+0

我只是覺得字典會很有用。之後我還計劃添加助攻,犯規等 - 所以我認爲如果沒有字典,它會變得太混亂。 – JoseBazBaz

回答

1

如果你是存儲在一個這樣的信息數據庫我會建議另一種方法:

class SoccerPlayer(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(80)) 
    team_id = db.Column(db.Integer, db.ForeignKey('Team.id')) 
    stats = db.relationship("Stats", uselist=False, backref="player") 


class Team(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(80)) 
    players = db.relationship("SoccerPlayer") 


class Stats(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    player_id = db.Column(db.Integer, db.ForeignKey('SoccerPlayer.id')) 
    goals_scored = db.Column(db.Integer) 
    assists = db.Column(db.Integer) 
    # Add more stats as you see fit 

在這種模式下的設置,你可以做瘋狂的事情像這樣:

from sqlalchemy.sql import func 

max_goals_by_team = db.session.query(Team.id, 
        func.max(Stats.goals_scored).label("goals_scored") 
       ). \ 
      join(SoccerPlayer, Stats). \ 
      group_by(Team.id).subquery() 

players = SoccerPlayer.query(Team.name.label("Team Name"), 
           SoccerPlayer.name.label("Player Name"), 
           max_goals_by_team.c.goals_scored). \ 
       join(max_goals_by_team, 
         SoccerPlayer.team_id == max_goals_by_team.c.id, 
         SoccerPlayer.stats.goals_scored == max_goals_by_team.c.goals_scored). 
       join(Team) 

從而使數據庫做拉出球員每隊的最高目標,而不是做這一切在Python的辛勤工作。

+0

你將如何初始化player_id以獲得統計信息(即,如何將它添加到def __init__方法中) – JoseBazBaz

0

甚至沒有django(比燒瓶更大的python web框架)不支持默認情況下。但在Django中,您可以安裝它,它被稱爲jsonfield(https://github.com/bradjasper/django-jsonfield)。

我想告訴你的是,並非所有的數據庫都知道如何存儲二進制文件,但他們知道如何爲django存儲字符串和jsonfield實際上是一個包含字典的json轉儲的字符串。

因此,簡而言之,你可以在瓶中做

import simplejson 

class SoccerPlayer(db.Model): 
    _data = db.Column(db.String(1024)) 

    @property 
    def data(self): 
     return simplejson.loads(self._data) 

    @data.setter 
    def data(self, value): 
     self._data = simplejson.dumps(value) 

但要注意,這樣你只能將整個字典一次:

player = SoccerPlayer() 
player.data = {'name': 'Popey'} 
print player.data # Will work as expected 
{'name': 'Popey'} 
player.data['score'] = '3' 
print player.data 
# Will not show the score becuase the setter doesn't know how to input by key 
{'name': 'Popey'} 
1

我會第二次採用肖恩提供的方法,在它得到正確的 規範化的數據庫模式之後,可以更容易地利用RDBMS爲您完成艱苦的工作。但是,如果 堅持在你的數據庫中使用類似字典的結構,我會建議 嘗試使用hstore 數據類型,它允許您將鍵/值對存儲爲 Postgres中的單個值。我不確定是否在默認情況下在Heroku提供的Postgres DB中創建了hstore擴展名,您可以通過在 psql內輸入\dx命令來檢查該擴展名。如果其中沒有hstore的行,則可以通過 輸入CREATE EXTENSION hstore;來創建它。

由於SQLAlchemy中的hstore支持在版本0中可用。8未 尚未公佈(但希望將在未來幾周內),你需要 從其Mercurial庫安裝:

pip install -e hg+https://bitbucket.org/sqlalchemy/sqlalchemy#egg=SQLAlchemy 

然後定義你的模型是這樣的:

from sqlalchemy.dialects.postgresql import HSTORE 
from sqlalchemy.ext.mutable import MutableDict 

class SoccerPlayer(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(80), nullable=False, unique=True) 
    stats = db.Column(MutableDict.as_mutable(HSTORE)) 

# Note that hstore only allows text for both keys and values (and None for 
# values only). 
p1 = SoccerPlayer(name='foo', stats={'goals_scored': '42'}) 
db.session.add(p1) 
db.session.commit() 

後你可以做平常的東西在你的查詢:

from sqlalchemy import func, cast 

q = db.session.query(
    SoccerPlayer.name, 
    func.max(cast(SoccerPlayer.stats['goals_scored'], db.Integer)) 
).group_by(SoccerPlayer.name).first() 

退房HSTORE docs 爲鐵道部例子。

相關問題