1

使用 Python/Flask/SQLAlchemy/Heroku。

想要将对象的字典存储为对象的属性:

澄清

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

^如何将姓名和进球数设置为一本字典?


更新:如果有任何区别,用户将输入名称和目标评分。

另外,我正在网上搜索合适的答案,但作为菜鸟,我无法理解/实现我在 Google 上为我的 Flask 网络应用程序找到的东西。

4

3 回答 3

2

我会支持 Sean 提供的方法,遵循它,您可以获得正确规范化的 DB 模式,并且可以更轻松地利用 RDBMS 为您完成艰苦的工作。但是,如果您坚持在数据库中使用类似字典的结构,我建议您尝试使用 hstore 数据类型,它允许您将键/值对作为单个值存储在 Postgres 中。我不确定hstoreHeroku 提供的 Postgres DB 中是否默认创建扩展名,您可以通过\dxpsql. 如果其中没有带有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 文档 以获取更多示例。

于 2012-12-12T14:00:46.743 回答
1

默认情况下,甚至 django(比flask 更大的 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'} 
于 2012-12-11T23:39:15.747 回答
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 完成。

于 2012-12-12T05:11:33.103 回答