sqlalchemy.exc.NoForeignKeysError: Can’t find any foreign key relationships

Filed in MySQL | Pyramid Leave a comment

Pyramidのわだい。
SQLAlchemyがいじわるな子になっている件。
掲題のエラーが出るんですよ。

全体感としては、
models.mymodel.pyの中で

Base = declarative_base()
MyModel(Base)

こう。MyModelクラスを切っておき、他のファイルの各モデルクラスがMyModelを継承するというかんじ。
models.employee.pyには

class Employee(MyModel):

こういうのがいますという形。
なんてことないというか、以前これで普通に使えていたはずなんだけどナーというところですが
sqlalchemy.exc.NoForeignKeysError: Can’t find any foreign key relationships between ‘models’ and ‘employee’.

むむむ。なんだよ。リレーションなんて張らないよ。継承元でしかないんだけどどういうことなの。

手当たり次第にぐぐります。

そして発見

if you want your NewBase to be a descendant of Base, then you’d need to put __abstract__=True on it. But if these cols are global to everyone you could make it the superclass of your declarative Base also by passing it as “class_” to declarative_base().
the naming conventions recipe is another way to go too.

新しいBase(たぶんdeclarative_baseのことなんだろう)を使うときは、__abstract__を使ってみてとある。
なんすかそれは。
入れてみますと、これが当たりでした。

こうするとよいということですね。

class MyModel(Base):
    __tablename__ = 'models'
    __abstract__=True
    id       = Column(Integer, primary_key=True)
    status   = Column(Integer, default=1)
    created  = Column(DateTime, default=datetime.datetime.now)
    updated  = Column(DateTime, default=datetime.datetime.now)

    def __init__(self, name, value):
        self.name = name

あ、えーとPEP8違反(=の両脇にスペースたくさん入れるのNG)の記述になってます。すいません。
PyCharmもあまりにこれガミガミ言うんで警告出さないようにしちゃった。すいません。
=の位置が揃ってないと気持ち悪いんだよ。

pip install umysqldbからのerror: command ‘gcc’ failed with exit status 1

Filed in MySQL | Pyramid | Python Leave a comment

あとで自分が検索できるようにと、エラーメッセージそのものをタイトルにしちゃっています。
重宝します。

経緯はともかく解決方法

aptitude install python-dev

うわあ。
身も蓋もなかったなあ。
gccがどうだのって言われて怯んでたんですけどね。

んで

pip install MySQL-Python

おわり。

よくは知りませんが、PythonのモジュールMySQLdbとかいうのはは死に体なのか、uMySQLdbってモジュールがPyPiでは人気あるようです。スコアが高いのね。
あたしは呼べればなんでもいいですが、カッコつけてコンパイルとかしといて、結局aptさんに入れてもらって解決とか意味がわからない。
あー
コンパイルオプションなんか忘れたのかもしれないなあ。

そしてfuelphpやるかとおもいきやpyramidでセットアップ

Filed in Jinja | Nginx | Pyramid | Python | SQLAlchemy Leave a comment

phpめんどくさいよ。仕事で使って、なんで要件好きに決められる自分のプロジェクトでも自らphp選択するんだよ。いみがわからない。
ということで、前の記事でphpをアレしてたのは一旦放っておき、愛するPyramidの環境をつくろうと思う。
Nginx+Python+Mysql、Pyramid+Jinja2。個人的にはmaaDBはなんでもいいですけどこの構成が好きです。
まともにアプリ書き終えるとこまで行ったことないですけどね。

pcreateでざざっと作ったあとで思い出す。
昔の記事で、このへんの構成を好みで動かしたやつがあった気がする。プロジェクトテンプレートを作っておけばよかった。手作業はまたディレクトリ指定間違えたりする凡ミスの温床なのよ。

「レンダリングされるビューは辞書を返すことができる」

Filed in Pyramid | Python Leave a comment

Pyramid。
レンダリングされるビューは辞書を返すことができる
うんそれがどーしたんすか、くらいの感覚だったんですが、HTMLやその部品を返す代わりに辞書を返すことで、テストが楽になるんだよと。
あー。
いまさら納得。

 @view_config(renderer='myapp:templates/mytemplate.pt')
 def myview(request):
     return {'a':1}

デコレータだっけ。なんでこんな面倒くさい感じのことやるんだろうと思ってたんですが、コレやらないと面倒くさいからだったわけですね。
賢くなった。

あらためてPyramid

Filed in Pylons | Pyramid | Python Leave a comment

なんかPyConも間近なんですが今年は行かない予定。モチベーションが。

そんなアレなのも何なので、重い腰を上げて久々にPyramidやらをさわろうと一念発起。
もうなんにもおぼえてないくぽー

さしあたり昔に書き散らしたいろんなアプリ(たいていはPylons)の残骸をかき集めて、それっぽい骨組みの構築開始。
scaffoldでjinja2+alchemyとかのなんかいいのがあればいいんだが無いっぽいので、両scaffoldで生成したプロジェクトの中身を見ながら合成。手でちくちく。scaffold自分で書けるようにならないとこの馬鹿馬鹿しい作業が一生ついてまわるのな。
で、そろそろ目鼻ついてきたかなというところで困ったのがルーティング。
なんか様子が変だ。

map.connectからconfig.add_routeへ

なんかルーティングの登録も仕組みが変わってるのね。
route とビューのサンプル — The Pyramid Cookbook v0.1 (翻訳)

「3.可変のコントローラとアクション。」のあたり。

Pyramid ではルーティング変数によってビュークラスを選択することは できません。

まてw
なにさらっと重要なこと書いてんだ。どうすんのそれ。

# Pylons
map.connect(“/{controller}/{action}”)
map.connect(“/{controller/{action}/{id}”)

こういうのできないって。
えー?

一個ずつ

config.add_route(“help”, “/help/{action}”)

こう書けってことかなあ。正気とは思えんなあ。なんの不都合があってそうしたんだろう。

と思いきや

“pyramid_routehelper” は、 Pylons の map.resource のように動作する config.add_resource メソッドを提供します。

もう。
なんなの。

initializedb.py

Filed in Pyramid | Python Leave a comment

initialize_Xxx_db.exeとかであれしますねDBの初期化とか。

 ../Scripts/initialize_Xxx_db development.ini

みたいな。
これどこでセットアップするテーブルの一覧見てんのかなーというと、
Xxx/xxx/scripts/initializedb.py
でした。

うちの環境は

models/
  models.py
  users.py

こうです。scaffoldのmodels.pyがそのまま生存しているのでなんか紛らわしい。よくない。よくないお。

で、件のinitializedb.pyのなかでモデル取り出してるところがあったのでー

from ..models.models import (
    DBSession,
    Base,
    )
from ..models import (
    models, users
    )

こんなふう。

#備考:
#あたしんちはmodelsディレクトリ切ってその中にモデルのファイルを入れています。
#なのでmodels/__init__pyにこんなふう。

# -*- coding:utf-8 -*-
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import (
    scoped_session,
    sessionmaker,
    )
from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()

ルート直下にviews.pyとか散らかしたくない

Filed in Jinja | Pyramid | Python Leave a comment

#pcreate -s alchemy Hoge で作ったプロジェクトを例にしています
App/app/views/views.py
とかしたい。

__init__.py

config.scan('.views')

このようにせいと、マニュアルに書いてある
この「.views」ってなんじゃ。ドットから始まるディレクトリ掘るというのはいささか悪趣味に感じるんだけど。

views掘ってみる。__init__.py置く。views.pyをそこに格納。
これだけだと

ImportError: No module named models

なんてerror吐かれて、あたしゃビューの面倒見てんのになんでモデルがしゃしゃり出てくるんだと奇妙な感じ。
なんだろうなあとviews.pyを眺めて、はたと膝を打つ。

from .models import (
    DBSession,
    MyModel,
    )

これだ。

from ..models import (
    DBSession,
    MyModel,
    )

こうする。微妙すぎてあれだけど、「.models」→「..models」になってる。
いつのバージョンだかからこういう指定の仕方できるようになったんですみたいな話を聞いていたのが救いになった。
で、件の「.views」も同じことだったわけかーと納得した次第です。
カレントディレクトリの下のviewsをscanするから「.views」なのねー。

あー。modelのスクリプトもmodels/models.pyとかにしたい場合は、views.pyでのモデルの場所指定も変わるね。

MakoじゃなくてJinja2使いたい

Filed in Jinja | Pyramid | Python Leave a comment

Pyramidのわだいです。

“.mak” または “.mako” で終わるテンプレートファイル名は Mako レンダラー に送られます。
“.html”のような他の拡張子が使いたければ、 main 関数に これを入れてください:
config.add_renderer(“.html”, “pyramid.mako_templating.renderer_factory”)
引用元

で、こういうののjinja2はどうしたらいいのか探してましたのよ。
pyramid.mako_templating.renderer_factory
これはなーに?どういう決まりでこれになってんの。分からない。
あたしはMakoを使うつもりがない。いいテンプレートエンジンなのは知ってる。少し。あたしの好みはJinja2でありGenshiなので、Jinja2が動いてくれないと嫌なのです。
#Genshiはちょっと気難しい子なので最近は避けてます(-_-;

Jinja2のテンプレートを食わせるまではうまく行った。
がしかし、拡張子「.jinja2」が非常に気に入らない。長いしダサいしそもそも数字がついてるのが非常に駄目だ。
あたしゃテンプレートの拡張子.htmlじゃなきゃ嫌なんだよ。
でもなんだか、中のほうで拡張子ごとにゴニョゴニョしている箇所があるらしく、テンプレートファイルとしてhoge.jinja2を単純にhoge.htmlとしてもうまくいかない。

あちこちさまよった結果、

config.add_renderer(".html", "pyramid_jinja2.renderer_factory")

__init__.pyでこうしてやるとうまくいった。.htmlでも食べるようになる。やった。
そもそもこの文字列はどこで見つけたのかというと、site-packagesのpyramid_jinja2見に行って、configure.zcmlつう怪しいファイルの中に書いてあるのを発見したという次第。
見つけ方合ってるのかわかりませんが解決したからいいんだ。

まとめ

当然のこととしてjinja2とpyramid_jinja2はいれとく

development.ini:

[app:main]に追記
jinja2.directories = %(here)s/{アプリ}/templates

pyramid.includesに追記
pyramid_jinja2

アプリ直下の__init__.py:

config = Configurator(settings=settings)
config.include('pyramid_jinja2')
config.add_renderer(".html", "pyramid_jinja2.renderer_factory")

まだ「リソースとビュー」の考えかたは染みこんできてない。
モデルよりフレームワークの仕掛けより、あたしはまず好みのテンプレートエンジンが動かないと気分的に落ち着かず、ただでさえ少ない集中力が減退する構造になっているんです。
というところがすっきりして、ひじょーに、こう、いいですね。
すっきりしました少し。

Pyramidにはコントローラがない

Filed in Pyramid | Python Leave a comment

絶対どこかで議論されたはず。混乱する人があたしだけ、なんてわけない。
そう、そんなわけはなかった。

「私は MVC ウェブフレームワークのユーザですが、混乱しています。 Pyramid はコントローラーをビューと呼んでいます! そして コントローラーがありません。」
引用元

これ。そしれこの文章自体が、Pyramid公式に載っているのをまんま引用したもの。
MVCがWebの仕事を正確に表現できてると思わないので、「リソースとビュー」というもので表現することにしましたと書いてある。
ええええ。

  • リソースツリーはサイト構造を表わします。
  • ビューは リソースを示します。
  • テンプレートは実際には単に任意のビューの実装詳細です
  • ビューは、レスポンスを返すためにテンプレートを必要としません。
  • 「コントローラー」は、ありません
  • 「モデル」は、 リソースツリー、またはフレームワークと完全に分離した「ドメインモデル」 (SQLAlchemy モデルのような) によって表わされます。

なんだそれは。
なんなんだそれは。
道理で、あたしの理解がまっったく進まないわけだ。
Pyramid使い始めてみたものの全然分からなくて、ああもうあたしのお脳の理解力の限界はここなのかお粗末な話だなこんちくしょう、って思ってたわけです。
10年近くくらいはMVCMVCって言われてきたんでないですか、Webの世界って。それがここにきて考え方を変えましょうときたわけで、そりゃ混乱するよねと。
リソースとビュー。
リソースとビューですよ奥さん。

config.add_route('home', '/')

こんなんやってる箇所が地図作ってるわけだな。
ツリー構造のurlマップみたいなのがリソースの地図になっていて、リソースそのものがビュー。
テンプレートは実装詳細です。そうですか。必ずしもテンプレートが必要なわけではないとあるあたりが理解の鍵なのかしらん。

モデルはフレームワークの格にあるんじゃなくて外側なんだと。そうなの、データって外側に位置するの。ちょっとイメージが出来てないですが、一旦そういうもんだと覚えることにする。
MVCのMに当たるのがーとか変換して考えちゃうから苦しむんであって、これはパラダイムが変わって別物が出てきたんですよというくらいで捉えるほうがよさそうです。

#あたしのお脳はまだついてきてません

Pyramidのプロジェクトをさくっと作る

Filed in Pyramid | Python Leave a comment

自分用メモ
各位ご存知のことかと存じますが、あたしはお脳のメモリ容量、アクセス速度共に石器時代あたりの人でありますので、pyramidのセットアップ一つをするりとやっつけるのにすらあちこちで転んでおりました。
わかってみると道理の通った手順なのですが、わかるまでが遠い。「何のためにこれやってんの」「どこに書いてあるの」「これやるとどうなるの」「いつおわるの(´・ω・`)」と不安になり腕が震え膝が体を支えられなくなり冷や汗が額を流れ落ちエトセトラ。
で、もうめんどくさいからこういうのを書いとけばいいんだよ。
#batファイルとして書いてるのでバックスラッシュです一部

:: pyramidstart.bat
@echo off
IF "%1" == "" (
    echo "pyramidstart env(virtualenv) project(pyramid)"
) else (
    virtualenv %1
    cd %1
    Scripts\activate
    pcreate -t alchemy %2
    cd %2
    pip install jinja2
    pip install pyramid_jinja2
    pip install -e .
    setup.py test -q
    \Scripts\initialize_%2_db development.ini
    echo "plz type: pserve development.ini --reload"
)

jinja2は入れただけなのでじつは

pyramid.includes =
    pyramid_jinja2

こういうのを(たぶん)書き加えてあげる必要があるんですが、さしあたりざくっと「Welcome to Hoge」画面を出すには足ります。
virtualenvの環境名fooenv
pyramidのプロジェクト名Foo
のばあい

pyramidstart fooenv Foo

とやると。

TOP