Comment refléter automatiquement la base de données à sqlalchemy declarative?

sqlautocode - a des problèmes avec plusieurs-à-plusieurs relations

sqlsoup - ne prend pas en charge les relations

elixir - il de la note auto-générer

Est-il autre chose que je pourrais essayer?

31
demandé sur mdob 2011-06-09 12:40:43

3 réponses

en théorie, la réflexion en sqlalchemy devrait fonctionner pour vous. Dans ce cas, j'utilise une base de données mssql avec deux tables qui ont une simple relation de plusieurs à une:

"Tests" avec les champs:

  • id
  • nomtest
  • author_id (clé étrangère de la table Users, Users.id field)

"Utilisateurs" avec les champs:

  • id
  • fullname

ainsi, ce qui suit devrait refléter le base de données:

from sqlalchemy import *
from sqlalchemy.orm import create_session
from sqlalchemy.ext.declarative import declarative_base

#Create and engine and get the metadata
Base = declarative_base()
engine = create_engine('put your database connect string here')
metadata = MetaData(bind=engine)

#Reflect each database table we need to use, using metadata
class Tests(Base):
    __table__ = Table('Tests', metadata, autoload=True)

class Users(Base):
    __table__ = Table('Users', metadata, autoload=True)

#Create a session to use the tables    
session = create_session(bind=engine)

#Here I will just query some data using my foreign key relation,  as you would
#normally do if you had created a declarative data mode.
#Note that not all test records have an author so I need to accomodate for Null records
testlist = session.query(Tests).all()    

for test in testlist:
    testauthor = session.query(Users).filter_by(id=test.author_id).first()  
    if not testauthor:
        print "Test Name: {}, No author recorded".format(test.testname)
    else:
        print "Test Name: {}, Test Author: {}".format(test.testname, testauthor.fullname)

donc cela semble fonctionner avec les relations de table. Bien que vous n'ayez toujours pas donné beaucoup de détails sur ce que vous essayez de faire.

67
répondu Raceyman 2011-06-10 14:26:27

Eh bien, je suis passé par là, essayé sur Northwind base de données et il semble prometteur. Bien que, j'ai dû ajouter le champ de relation pour pouvoir suivre les relations de base de données.

considérons que je ne connais pas les relations entre les tables au moment de commencer l'application donc j'ai besoin d'un moyen de générer automatiquement.

import unittest

from sqlalchemy import *
from sqlalchemy.orm import create_session
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
from sqlalchemy.orm import contains_eager, joinedload
from sqlalchemy.orm import relationship

#Create and engine and get the metadata
Base = declarative_base()
engine = create_engine('mssql://user:pass@Northwind', echo=True)
metadata = MetaData(bind=engine)


#Reflect each database table we need to use, using metadata
class Customer(Base):
    __table__ = Table('Customers', metadata, autoload=True)
    orders = relationship("Order", backref="customer")

class Shipper(Base):
    __table__ = Table('Shippers', metadata, autoload=True)
    orders = relationship("Order", backref="shipper")

class Employee(Base):
    __table__ = Table('Employees', metadata, autoload=True)
#    orders = relationship("Order", backref="employee")
    territories = relationship('Territory', secondary=Table('Employeeterritories', metadata, autoload=True))

class Territory(Base):
    __table__ = Table('Territories', metadata, autoload=True)
    region = relationship('Region', backref='territories')

class Region(Base):
    __table__ = Table('Region', metadata, autoload=True)


class Order(Base):
    __table__ = Table('Orders', metadata, autoload=True)
    products = relationship('Product', secondary=Table('Order Details', metadata, autoload=True))
    employee = relationship('Employee', backref='orders')

class Product(Base):
    __table__ = Table('Products', metadata, autoload=True)
    supplier = relationship('Supplier', backref='products')
    category = relationship('Category', backref='products') 

class Supplier(Base):
    __table__ = Table('Suppliers', metadata, autoload=True)

class Category(Base):
    __table__ = Table('Categories', metadata, autoload=True)


class Test(unittest.TestCase):

    def setUp(self):
        #Create a session to use the tables    
        self.session = create_session(bind=engine)        

    def tearDown(self):
        self.session.close()

    def test_withJoins(self):
        q = self.session.query(Customer)
        q = q.join(Order)
        q = q.join(Shipper)
        q = q.filter(Customer.CustomerID =='ALFKI')
        q = q.filter(Order.OrderID=='10643')
        q = q.filter(Shipper.ShipperID=='1')
        q = q.options(contains_eager(Customer.orders, Order.shipper))
        res = q.all()
        cus = res[0]
        ord = cus.orders[0]
        shi = ord.shipper
        self.assertEqual(shi.Phone, '(503) 555-9831')
23
répondu mdob 2011-06-22 10:48:00

Vous pouvez utiliser sqlacodegen pour générer tous les modèles à partir de la base de données. Cependant, vous devez prendre soin de la clé étrangère manuellement.

23
répondu Indradhanush Gupta 2013-07-15 09:49:09