1

Python/Flask/SQLAlchemy/Heroku を使用します。

オブジェクトの辞書をオブジェクトのプロパティとして保存したい:

明確にするために

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

^ 名前と得点を 1 つの辞書として設定するにはどうすればよいですか?


更新: 違いがある場合、ユーザーは名前と goal_scored を入力します。

また、適切な回答をオンラインで検索していますが、初心者として、Flask Web アプリについて Google で見つけたものを理解/実装できていません。

4

3 に答える 3

2

適切に正規化された DB スキーマを取得し、RDBMS をより簡単に利用して難しい作業を行うことができれば、Sean によって提供されたアプローチを支持します。ただし、DB 内で辞書のような構造を使用することを主張する場合は、 キーと値のペアを単一の値として Postgres に格納できるhstoreデータ型を試すことをお勧めします。hstoreHeroku が提供する Postgres DB で拡張機能がデフォルトで作成されて\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 ドキュメントをご覧ください 。

于 2012-12-12T14:00:46.743 に答える
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'} 
于 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 に答える