使用Python / Flask / SQLAlchemy / Heroku。
想要将对象的字典存储为对象的属性:
要澄清
class SoccerPlayer(db.Model):
name = db.Column(db.String(80))
goals_scored = db.Column(db.Integer())
^我如何设置得分为一个字典的名称和目标?
更新:如果有任何不同,用户将输入名称和goals_scored。
此外,我正在网上搜索一个合适的答案,但作为一个菜鸟,我无法理解/实现我在Google上为我的Flask网络应用程序找到的内容。
答案 0 :(得分:1)
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 :(得分: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中完成所有这些。
答案 2 :(得分:1)
我会选择Sean提供的方法,然后你就可以了
规范化的数据库模式,可以更轻松地利用RDBMS为您完成艰苦的工作。如果,
但是,你坚持在你的数据库中使用类似字典的结构,我会
建议尝试hstore
数据类型,允许您将键/值对存储为单个值
Postgres的。我不确定Postgres默认是否创建hstore
扩展名
Heroku提供的数据库,您可以通过在里面输入\dx
命令来检查
psql
。如果其中没有包含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 更多例子。