2009-04-23 33 views
15

Tôi có câu hỏi liên quan đến SQLAlchemy. Làm thế nào tôi có thể thêm vào lớp được ánh xạ của tôi thuộc tính giống như từ điển, ánh xạ các khóa chuỗi thành các giá trị chuỗi và sẽ được lưu trữ trong cơ sở dữ liệu (trong cùng một bảng khác với đối tượng được ánh xạ ban đầu). Tôi muốn điều này thêm hỗ trợ cho các thẻ tùy ý của đối tượng của tôi.SQLAlchemy - Từ điển của các thẻ

tôi thấy ví dụ sau đây trong tài liệu SQLAlchemy:

from sqlalchemy.orm.collections import column_mapped_collection, attribute_mapped_collection, mapped_collection 

mapper(Item, items_table, properties={ 
# key by column 
'notes': relation(Note, collection_class=column_mapped_collection(notes_table.c.keyword)), 
# or named attribute 
'notes2': relation(Note, collection_class=attribute_mapped_collection('keyword')), 
# or any callable 
'notes3': relation(Note, collection_class=mapped_collection(lambda entity: entity.a + entity.b)) 
}) 

item = Item() 
item.notes['color'] = Note('color', 'blue') 

Nhưng tôi muốn các hành vi sau đây:

mapper(Item, items_table, properties={ 
# key by column 
'notes': relation(...), 
}) 

item = Item() 
item.notes['color'] = 'blue' 

Có thể trong SQLAlchemy?

Cảm ơn bạn

Trả lời

21

Câu trả lời đơn giản là .

Chỉ cần sử dụng một proxy hiệp hội:

from sqlalchemy import Column, Integer, String, Table, create_engine 
from sqlalchemy import orm, MetaData, Column, ForeignKey 
from sqlalchemy.orm import relation, mapper, sessionmaker 
from sqlalchemy.orm.collections import column_mapped_collection 
from sqlalchemy.ext.associationproxy import association_proxy 

Tạo một môi trường thử nghiệm:

engine = create_engine('sqlite:///:memory:', echo=True) 
meta = MetaData(bind=engine) 

Xác định các bảng:

tb_items = Table('items', meta, 
     Column('id', Integer, primary_key=True), 
     Column('name', String(20)), 
     Column('description', String(100)), 
    ) 
tb_notes = Table('notes', meta, 
     Column('id_item', Integer, ForeignKey('items.id'), primary_key=True), 
     Column('name', String(20), primary_key=True), 
     Column('value', String(100)), 
    ) 
meta.create_all() 

lớp (chú ý association_proxy trong lớp):

class Note(object): 
    def __init__(self, name, value): 
     self.name = name 
     self.value = value 
class Item(object): 
    def __init__(self, name, description=''): 
     self.name = name 
     self.description = description 
    notes = association_proxy('_notesdict', 'value', creator=Note) 

Mapping:

mapper(Note, tb_notes) 
mapper(Item, tb_items, properties={ 
     '_notesdict': relation(Note, 
      collection_class=column_mapped_collection(tb_notes.c.name)), 
    }) 

Sau đó chỉ cần kiểm tra nó:

Session = sessionmaker(bind=engine) 
s = Session() 

i = Item('ball', 'A round full ball') 
i.notes['color'] = 'orange' 
i.notes['size'] = 'big' 
i.notes['data'] = 'none' 

s.add(i) 
s.commit() 
print i.notes 

Đó in:

{u'color': u'orange', u'data': u'none', u'size': u'big'} 

Nhưng, những người trong bảng ghi chú?

>>> print list(tb_notes.select().execute()) 
[(1, u'color', u'orange'), (1, u'data', u'none'), (1, u'size', u'big')] 

Nó hoạt động !! :)

+0

Làm cách nào để xóa 'i'?Tôi nhận được một 'aise AssertionError (" Quy tắc phụ thuộc cố gắng để trống ra cột khóa chính '% s' trên ví dụ '% s' "% (r, mapperutil.state_str (dest)))' ngoại lệ khi thử 's.delete (i) ' – Sardathrion

+0

Trả lời câu hỏi của riêng tôi:' Trong bản đồ (mục [...], cascade = "tất cả, xóa-mồ côi"), [...] ' – Sardathrion

-6

Câu trả lời đơn giản là 'không'.

SQLAlchemy là trình bao bọc trên cơ sở dữ liệu SQL.

Ví dụ về mối quan hệ bạn trích dẫn mối quan hệ giữa các bảng SQL thành cấu trúc giống như bản đồ Python để làm cho nó đơn giản hơn một chút để thực hiện các câu lệnh SQL SELECT và định vị các hàng trong bảng khác.

Các

item.notes['color'] = Note('color', 'blue') 

là điều cần thiết vì Note là một bảng riêng biệt với hai cột. Bạn không thể rời khỏi phần Note.

Bạn phải xác định bảng SQL khác này và bạn phải tạo các đối tượng được ánh xạ tới bảng SQL đó.

Các vấn đề liên quan