Mọi thứ đều có trong tiêu đề. Có cách "Pythonic" (ý tôi là, không có truy vấn SQL thuần túy) nào để định nghĩa một khung nhìn SQL với SQLAlchemy?Cách tạo Chế độ xem SQL với SQLAlchemy?
Cảm ơn sự giúp đỡ của bạn,
Mọi thứ đều có trong tiêu đề. Có cách "Pythonic" (ý tôi là, không có truy vấn SQL thuần túy) nào để định nghĩa một khung nhìn SQL với SQLAlchemy?Cách tạo Chế độ xem SQL với SQLAlchemy?
Cảm ơn sự giúp đỡ của bạn,
Cập nhật: Xem thêm việc sử dụng SQLAlchemy recipe here
Tạo (read-only không thể hóa) xem không được hỗ trợ ra khỏi hộp như xa như tôi biết. Nhưng việc thêm chức năng này vào SQLAlchemy 0.7 là đơn giản (tương tự như ví dụ tôi đã đưa ra here). Bạn chỉ cần viết compiler extensionCreateView
. Với phần mở rộng này, bạn có thể viết (giả định rằng t
là một đối tượng bảng với một cột id
)
createview = CreateView('viewname', t.select().where(t.c.id>5))
engine.execute(createview)
v = Table('viewname', metadata, autoload=True)
for r in engine.execute(v.select()):
print r
Dưới đây là một ví dụ làm việc:
from sqlalchemy import Table
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Executable, ClauseElement
class CreateView(Executable, ClauseElement):
def __init__(self, name, select):
self.name = name
self.select = select
@compiles(CreateView)
def visit_create_view(element, compiler, **kw):
return "CREATE VIEW %s AS %s" % (
element.name,
compiler.process(element.select, literal_binds=True)
)
# test data
from sqlalchemy import MetaData, Column, Integer
from sqlalchemy.engine import create_engine
engine = create_engine('sqlite://')
metadata = MetaData(engine)
t = Table('t',
metadata,
Column('id', Integer, primary_key=True),
Column('number', Integer))
t.create()
engine.execute(t.insert().values(id=1, number=3))
engine.execute(t.insert().values(id=9, number=-3))
# create view
createview = CreateView('viewname', t.select().where(t.c.id>5))
engine.execute(createview)
# reflect view and print result
v = Table('viewname', metadata, autoload=True)
for r in engine.execute(v.select()):
print r
Nếu bạn muốn, bạn cũng có thể chuyên cho một phương ngữ, ví dụ
@compiles(CreateView, 'sqlite')
def visit_create_view(element, compiler, **kw):
return "CREATE VIEW IF NOT EXISTS %s AS %s" % (
element.name,
compiler.process(element.select, literal_binds=True)
)
Chế độ xem SQL không có SQL thuần túy? Bạn có thể tạo lớp hoặc chức năng để triển khai chế độ xem được xác định.
function get_view(con):
return Table.query.filter(Table.name==con.name).first()
Xin lỗi nhưng đó không phải những gì tôi yêu cầu. Tiếng Anh của tôi không hoàn hảo, tôi xin lỗi nếu bạn hiểu lầm :) –
Những ngày này có gói PyPI cho điều đó: SQLAlchemy Views.
Từ đó PyPI Page:
>>> from sqlalchemy import Table, MetaData
>>> from sqlalchemy.sql import text
>>> from sqlalchemy_views import CreateView, DropView
>>> view = Table('my_view', metadata)
>>> definition = text("SELECT * FROM my_table")
>>> create_view = CreateView(view, definition, or_replace=True)
>>> print(str(create_view.compile()).strip())
CREATE OR REPLACE VIEW my_view AS SELECT * FROM my_table
Tuy nhiên, bạn yêu cầu một không "SQL tinh khiết" truy vấn, vì vậy bạn có thể muốn definition
trên để được tạo ra với đối tượng truy vấn SQLAlchemy.
May mắn thay, text()
trong ví dụ trên làm cho thông số definition
thành CreateView
là một đối tượng truy vấn như vậy. Vì vậy, một cái gì đó như thế này nên làm việc:
>>> from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
>>> from sqlalchemy.sql import select
>>> from sqlalchemy_views import CreateView, DropView
>>> metadata = MetaData()
>>> users = Table('users', metadata,
... Column('id', Integer, primary_key=True),
... Column('name', String),
... Column('fullname', String),
...)
>>> addresses = Table('addresses', metadata,
... Column('id', Integer, primary_key=True),
... Column('user_id', None, ForeignKey('users.id')),
... Column('email_address', String, nullable=False)
... )
Đây là chút thú vị:
>>> view = Table('my_view', metadata)
>>> definition = select([users, addresses]).where(
... users.c.id == addresses.c.user_id
...)
>>> create_view = CreateView(view, definition, or_replace=True)
>>> print(str(create_view.compile()).strip())
CREATE OR REPLACE VIEW my_view AS SELECT users.id, users.name,
users.fullname, addresses.id, addresses.user_id, addresses.email_address
FROM users, addresses
WHERE users.id = addresses.user_id
Tôi có thể sử dụng bản đồ v với orm.mapper không? như 'v = Bảng ('viewname', siêu dữ liệu, tự động load = True) lớp ViewName (object): def __init __ (tự, tên): self.name = tên mapper (ViewName, v) ' Trên đây là có thể? Bởi vì tôi sẽ sử dụng Xem với phiên. –
@SyedHabibM: vâng, điều này là có thể. Tuy nhiên, bạn phải đặt khóa chính theo cách thủ công, giống như 'orm.mapper (ViewName, v, primary_key = pk, thuộc tính = prop)' trong đó 'pk' và' prop' là khóa chính của bạn (hoặc các khóa) và thuộc tính tương ứng . Xem http://docs.sqlalchemy.org/en/latest/orm/mapper_config.html#sqlalchemy.orm.mapper. – stephan
@SyedHabibM: bạn có thể làm những gì * stephan * cũng đề cập khi bạn sử dụng bảng tự động tải bằng cách ghi đè đặc tả cột và chỉ định PK: 'v = Bảng ('viewname', siêu dữ liệu, Cột ('my_id_column', Integer, primary_key = True), autoload = True) ' – van