2012-03-19 27 views

Trả lời

51

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) 
     ) 
+0

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. –

+1

@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

+2

@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

-7

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() 
+1

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 :) –

4

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 
Các vấn đề liên quan