2016-12-12 16 views
0

私は非常に単純なフラスコアプリをpostgresqlデータベースに接続しています。私は主にflask-adminのフラスコアプリを使用しているので、データベースにレコードを追加し、後でダッシュボードに保存することができます。基本的には内部使用カタログです。sqlalchemyセッションを作成する*または多くの関係を持つレコードを作成する

私がしようとしているのは、サードパーティのAPIに接続してデータベースにレコードを追加/更新するためのスクリプトを作成するため、フラスコのアプリケーションを通過しないためです。私はSQLAlchemyを使用しています。なぜなら、これはアプリケーションとの一貫性があり、SQL文を悩ますことなく作業する必要があるからです。

フラスコアプリのデータモデルは、次のように定義されます

app.py

from flask import Flask, render_template, request 
from flask_sqlalchemy import SQLAlchemy 
from sqlalchemy.dialects import postgresql 
from flask_admin import Admin 

# ... APPLICATION CONFIGURATION ... 

# db Models 

## Table for many to many 
keywords = db.Table('keywords', 
    db.Column('keyword_id', db.Integer, db.ForeignKey('keyword.id')), 
    db.Column('dataset_id', db.String(24), db.ForeignKey('dataset.dataset_id')), 
) 

## Model classes 
class Dataset(db.Model): 
    title = db.Column(db.String(120)) 
    description = db.Column(db.Text()) 
    dataset_id = db.Column(db.String(24), primary_key=True, unique=True) 

    #relationships 
    dataset_documentation = db.relationship('DataDocument', backref='dataset', lazy='dynamic') 
    keywords = db.relationship('Keyword', secondary=keywords, backref='dataset', lazy='dynamic') 

    def __str__(self): 
     return self.title 

class Keyword(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    keyword = db.Column(db.String(80)) 

    def __str__(self): 
     return self.keyword 

class DataDocument(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    document = db.Column(db.String(120)) 
    dataset_id = db.Column(db.String(24), db.ForeignKey('dataset.dataset_id')) 

    def __str__(self): 
     return self.document 

# ... APPLICATION VIEWS ... 

だから、我々はいくつかの基本的なメタデータとdatasetsを持っており、彼らはファイルパスを持つ多くの関係に1を持っていますドキュメント、および任意の数のキーワードとの多対多の関係

別のスクリプトは、データベースに直接接続し、既存のテーブルをセッションの作成とデータベースの変更に使用できるオブジェクトにマッピングしています。

import config #local config only 
from sqlalchemy import create_engine, MetaData, Table 
from sqlalchemy.orm import mapper, sessionmaker 


# Connecting to postgres database and creating a session with database objects, intantiate empty classes to populate 
class Dataset(object): 
    pass 

class DataDocument(object): 
    pass 

class Keyword(object): 
    pass 

## How to instantiate the MTM association table? 

db_uri = config.SQLALCHEMY_DATABASE_URI 
engine = create_engine(db_uri) 
meta = MetaData(engine) 
dataset_table = Table('dataset', meta, autoload=True) #correct 
datadocument_table = Table('dataset', meta, autoload=True) #incorrect? 
keyword_table = Table('keyword', meta, autoload=True) #incorrect? 
mapper(Dataset, dataset_table) #correct 
mapper(DataDocument, datadocument_table, meta, autoload=True) #?? 
mapper(Keyword, keyword_table, meta, autoload=True) #?? 

Session = sessionmaker(bind=engine) 
session = Session() 
# sample update 

data_upsert = Dataset() 
data_upsert.title = "Some title" 
data_upsert.dataset_id = "Uniq_ID-123" 
data_upsert.description = "lorem ipsum foo bar foo" 

session.merge(data_upsert) 

#attempt to add related properties 

key1 = Keyword('test1') 
key2 = Keyword('test2') 
datadoc = DataDocument('path/to/document.txt') 

# FAIL. 

data_upsert.append(key1) 
data_upsert.append(key2) 
data_upsert.append(datadoc) 

session.flush() 

script.py私はSQLAlchemyのと初心者と私はかろうじてデータベースエンジンからスクリプトでDatasetオブジェクトを作成まわりで私の頭をラップすることができます。しかし、私はKeywordDatadocumentテーブルをロードすることも考えていましたが、データベースから読み込んでいるものに基づいて関係をすでに理解していると思いますが、これは私の理解が薄いものです。

ここで写真を完成させる簡単な方法はありますか?私はscript.pyでモデルを明示的に定義するのは意味がないと仮定していますが、ドキュメンテーションとチュートリアルを見直す際に、これらの関係をセッションに読み込むという欠点を見ていないので、すべてのデータをデータベース。

答えて

0

コンストラクタ関数を追加するためにモデル定義を更新します。その場合、インスタンス化時にオブジェクトにパラメータを渡すことができます。

models.py

## Model classes 
class Dataset(db.Model): 
    title = db.Column(db.String(120)) 
    description = db.Column(db.Text()) 
    dataset_id = db.Column(db.String(24), primary_key=True, unique=True) 

    #relationships 
    dataset_documentation = db.relationship('DataDocument', backref='dataset', lazy='dynamic') 
    keywords = db.relationship('Keyword', secondary=keywords, backref='dataset', lazy='dynamic') 

    def __init__(self, title=None, desc=None, dataset_id=None): 
     self.title = title 
     self.description = desc 
     self.dataset_id = dataset_id 

    def __str__(self): 
     return self.title 


class Keyword(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    keyword = db.Column(db.String(80)) 

    def __init__(self, keyword=None): 
     self.keyword = keyword 

    def __str__(self): 
     return self.keyword 


class DataDocument(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    document = db.Column(db.String(120)) 
    dataset_id = db.Column(db.String(24), db.ForeignKey('dataset.dataset_id')) 

    def __init__(self, document, dataset_id): 
     self.document = document 
     self.dataset_id = dataset_id 

    def __str__(self): 
     return self.document 

script.pyに再びモデルクラスを定義する必要はありません。使用したいクラスをmodels.pyから単純にインポートすることができます。私はローカルでコードをテストしてみた

import config #local config only 
from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 
from models import Dataset, DataDocument, Keyword 


def loadSession(engine): 
    """""" 
    Session = sessionmaker(bind=engine) 
    session = Session() 
    return session 


engine = create_engine(config.SQLALCHEMY_DATABASE_URI, echo=False) 
Base = declarative_base(engine) 
# load session 
session = loadSession(engine) 
data_upsert = Dataset(title="Some title", dataset_id="Uniq_ID-125", desc="lorem ipsum foo bar foo") 

# add related properties here 
key1 = Keyword('test1') 
key2 = Keyword('test2') 
datadoc = DataDocument('path/to/document.txt', dataset_id="Uniq_ID-125") 

# append the properties to the object 
data_upsert.dataset_documentation.append(datadoc) 
data_upsert.keywords.append(key1) 
data_upsert.keywords.append(key2) 

session.add(data_upsert) 

session.commit() 

script.py、それはあなたのために働く願っています:そして、あなたは完全にこのようにデータベースにその関連オブジェクトとデータオブジェクトを挿入することができます。

関連する問題