10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Flask, EveでREST+NormalSite構築のはまりどころ

Posted at

Flaskの派生のひとつでRESTサービスを簡単に構築できるEveというのがある。スキーマの設計さえしておけば、SiteRootにREST APIを展開してくれる優れものだが、Django+REST Framework+angularのような感じで、構築しようとしたときに結構はまったので記録に残しておく。

##REST API Rootの変更
Eveの場合通常API Root=Rootとなるので、rootアクセス時にindex.html表示なんてことができない。
そこで、

settings.py
URL_PREFIX = 'api'

みたく、prefixを定義してやることで、APIルートを変更できる。

##Flask とEveの設定
EveとFlaskで別々に設定がある。
Eveは指定しないと同じディレクトリのsettings.pyを読みに行く。
別途読み込みたい場合は

app=EVE(settings='hoge.py')

と書くとそちらを読みに行く。ただし、settingsはdictとfileしか受け付けない。

Eveが使用している設定以外はsettings.pyに書いても機能しないはず・・・
Flaskの設定は切り離して、create_app()などのappFactoryで与える必要がある。

app/__init__.py
def create_app(api_settings=None, flask_config='oss_app.config', package_name=__name__, flask_conf_override=None):

    # Define the WSGI application object
    if api_settings is not None:
        app = Eve(settings=api_settings, import_name=__name__)
    else:
        app = Eve()

    # Configurations
    app.config.from_object(flask_config)
    app.config.from_object(flask_conf_override)

##static path
Eveの場合、無設定で/staticをたたくと、404が返ってくる。
理由はeveのパッケージのflaskapp.pyで

flaskapp.py
class Eve(Flask, Events):

 中略

    def __init__(self, import_name=__package__, settings='settings.py',
                 validator=Validator, data=Mongo, auth=None, redis=None,
                 url_converters=None, json_encoder=None,
                 media=GridFSMediaStorage, **kwargs):

となっている。
Flaskはstatic_root_pathを探す時に、import_nameがあるとimport_nameを探すので、import_name=package=EVEとなり、site-package内のEVEディレクトリがsatticfileのディレクトリと認識してしまい、404が返ってしまう。
対策はEveインスタンス生成時にimport_name=__name__としてやること。

app=Eve(import_name=__name__)

##Eve-mongoengineを使う。
Eveの場合、初期状態はpymongoを使用する、ORMを使用したい場合、Eve-mongoengineが使える。ただし、1年ほど更新が止まっているためか、使用すると起動シークエンスで_etag errorとなり落ちる。
EveのどこかのバージョンからEtagあが必須になったのだが追い付いていないのだと思う。
これにについては
eve-mongoengine\_init.pyの102行目あたりと190行目あたりにEtagの定義追加で何とかなる。

eve-mongoengine__init_.py

91:
    def _parse_config(self):
        # parse app config
        config = self.app.config
        try:
            self.last_updated = config['LAST_UPDATED']
        except KeyError:
            self.last_updated = '_updated'
        try:
            self.date_created = config['DATE_CREATED']
        except KeyError:
            self.date_created = '_created'
+        try:
+            self.etag = config['ETAG']
+        except KeyError:
+            self.etag = '_etag'

    def fix_model_class(self, model_cls):

中略
192:
        date_field_cls = mongoengine.DateTimeField
+        string_field_cls = mongoengine.StringField

        # field names have to be non-prefixed
        last_updated_field_name = self.last_updated.lstrip('_')
+        date_created_field_name = self.date_created.lstrip('_')
        etag__field_name = self.etag.lstrip('_')
        new_fields = {
            # TODO: updating last_updated field every time when saved
            last_updated_field_name: date_field_cls(db_field=self.last_updated,
                                                    default=get_utc_time),
            date_created_field_name: date_field_cls(db_field=self.date_created,
                                                    default=get_utc_time),
             etag__field_name: string_field_cls(db_field=self.etag,
                                                    default=""),
        }

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?