db クエリを使用する適切な方法を見つけるのに問題があります。私は Web 開発の経験があまりありません。勤務時間外に 6 か月間 (つまり、週に最大 10 時間) 働いているようなものです。私が Pyramid を選んだのは、主に Py3k をサポートしているためです。django やチュートリアルほど多くのコミュニティ サポートがないため、間違ったことをしている可能性があります。そう...
私は Pyramid(1.4) と SQLAlchemy (0.8) を使用しています。Pyramid のチュートリアルで説明されているとおりにプロジェクトを作成しました。
の使用に関するこの優れた投稿 ( https://stackoverflow.com/a/11547942/1498245 )を既に読みましたscoped_session
。
しかし..私は、DBオブジェクトの処理に対する適切な(存在する場合)アプローチに苦労しています。
だからここに私が始めたものがあります:
## Project layout
myproject
├── models
│ ├── somemodel1.py
│ ├── somemodel2.py
│ ├── __init__.py
│ ├── meta.py
│ └── somemodel3.py
├── schemas
│ ├── some_colander_schema1.py
│ ├── some_colander_schema2.py
│ └── some_colander_schema3.py
├── scripts
│ ├── __init__.py
│ └── initializedb.py
├── static
│ ├── bootstrap
│ ├── favicon.ico
│ ├── jquery-1.9.1.min.js
│ └── transparent.gif
├── templates
│ ├── some_chameleon_template.pt
│ ├── some_chameleon_template1.pt
│ ├── some_chameleon_template2.pt
│ ├── forbidden_view.pt
│ ├── global_layout_noauth.pt
│ └── global_layout.pt
├── views
│ ├── someviewclass1.py
│ ├── someviewclass2.py
│ └── someviewclass3.py
└── __init__.py
# models/meta.py PRE @contextmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
DBSession = scoped_session(sessionmaker())
Base = declarative_base()
さて、要点です。
私の見解では、次の構成を使用していました。
class SomeView1(Layout): #in Layout class request is saved to self.request
@view_config(...)
def list(self):
DBSession()
try:
somethings = DBSession.query(SomeModel).options(eagerload(...)).filter(...).all()
except: #it's bad to catch everything I know, but had to close session properly
somethings = []
DBSession.rollback()
DBSession.remove()
... #do something more
DBSession()
try:
somethingMores = DBSession.query(SomeModel2).options(eagerload(...)).filter(...).all()
except: #it's bad to catch everything I know, but had to close session properly
somethingMores = []
DBSession.rollback()
DBSession.remove()
return {"values" : somethings,
"others" : somethingMores}
@view_config(...)
def edit(self):
# here's recently implemented "update"
DBSession()
try:
somethings = DBSession.query(SomeModel1)...all()
somethingsMore = DBSession.query(SomeModel2)...all()
finally:
DBSession.remove()
return {"somethings":somethings,
"somethingsMore": somethingsMore}
しかし、そのようなクエリがたくさんあることに気付きました..それで、それらをモデルに移動しました。
私の見解では、私はただ電話しなければなりませんでした:
somethings = SomeModel1.all()
#or
something = SomeModel.by_id(some_id)
その中でSomeModel1
、例えば:
class SomeModel(Base):
__tablename__ = "somemodel"
idsomeModel = Column(Integer, primary_key=True)
@classmethod
def all(cls):
DBSession()
try:
retval = ...
except:
retval = None
finally:
DBSession.remove()
return retval
それはすべて素晴らしいです(実際にはそうではありませんが、待って..)が、たとえばソート順やwhere句を配置する必要がある場合は厄介になります。次に、次のような多くのs にdef all(cls)
変わりました。def all(cls, **kwargs)
if
query = DBSession.query(SomeModel)
if "forPeriod" in kwargs:
query = query.filter(SomeModel.date > kwargs["forPeriod"])
if "sortOrder" in kwargs:
query = query.order_by(kwargs["sort"])
retval = query.all()
大丈夫ですか?または、ビューにクエリを記述する必要がありますか? 「良い方法」はないと思いますが、このアプローチの方が保守しやすいと思います。
そして、それは良くありません。今、私は sqlalchemy サイトで、セッションをモデルに渡す方がはるかに優れていることを読みました。このように、私の見解では、次のように使用します。
@view_config(...)
def some_function(self):
with get_db_session as session:
somethings = SomeModel.all(session, some_arguments)
その関数get_db_session
は new からのものですmodels/meta.py
:
# models/meta.py
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
from contextlib import contextmanager
DBSession = scoped_session(sessionmaker())
Base = declarative_base()
@contextmanager
def get_scoped_session():
try:
yield DBSession()
finally:
DBSession.remove()
とんでもない投稿ですが、誰かに「よし、いい方向に進んでいる」とか「いや、クソ野郎、何してるの?」と言ってもらいたいです。
すべてを要約すると:
モデルでクエリを非表示にすることは良い考えですか? (時にはたくさんの
if
s onkwargs
; とあいまいな例外があります - そのようなことが起こった場合、私の戻り値は None です。なぜなら、私は理由が何であったか気にしないので、(モデルで) ログに記録しました)このような scoped_session
@contextmanager
とwith
ステートメントの使用は良いアプローチですか?いいえ、3 番目の質問はありません.. 2 つの質問をするためだけにテキストが多すぎます :/