2017-02-20 38 views
0

我有一個多對一的關係數據庫。在我的聲明系統中,我打電話給relationship(),如下例所示。出於某種原因,我想保留所有Features排序。不幸的是,排序邏輯非常複雜,並且使用多個屬性來完成。如何在SQLAlchemy關係()中使用sortedcontainers.SortedList?

from sortedcontainers import SortedList 
from sqlalchemy.orm import relationship 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import Column, Integer, Text 
from sqlalchemy import ForeignKey 
from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 

Base = declarative_base() 

class Product(Base): 
    __tablename__ = 'products' 
    id = Column(Integer, primary_key=True, autoincrement=True) 
    name = Column(Text) 

class Feature(Base): 
    __tablename__ = 'features' 
    id = Column(Integer, primary_key=True, autoincrement=True) 
    productid = Column(Integer, ForeignKey('products.id')) 
    attr = Column(Integer) 

    product = relationship('Product', back_populates='features') 
    Product.features=relationship('Feature', collection_class=SortedList, back_populates='product') 

    def __eq__(self, other): 
     # some magic here, simplified... 
     return self.attr == other.attr 

    def __lt__(self, other): 
     # some magic here, simplified... 
     return self.attr < other.attr 

    def __le__(self, other): 
     # some magic here, simplified... 
     return self.attr <= other.attr 

engine = create_engine('sqlite:///test.db') 
Session = sessionmaker(bind=engine) 
Base.metadata.create_all(engine) 

我已經充滿了下列值的數據庫:

sqlite> select * from products; 
id   name  
---------- ---------- 
1   Product1 
sqlite> select * from features; 
id   productid attr  
---------- ---------- ---------- 
1   1   42   
2   1   1  

當我嘗試加載(通過訪問)的值,sortedcontainers.SortedList引發一個ValueError異常,大概是因爲它正在嘗試加載無序結果。當功能按順序存儲時,沒有問題。

In [1]: from test import * 
In [2]: session = Session() 
In [3]: p = session.query(Product).first() 
In [4]: for f in p.features: 
    print("id: %d\tattr: %d" % (f.id, f.attr)) 
    ...:  
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
# traceback 
ValueError: <test.Feature object at 0x7f68da5d2208> not in sort order at index 1 

我知道在這個特殊的情況下,解決方案是使用relationship()的說法order_by但我的使用情況是更復雜,因爲排序使用幾個列的值。

那麼,有沒有我錯過了使用SQLAlchemy或我應該嘗試找到一種解決方法?

回答

0

好吧,我終於找到了一個非常簡單的解決方案看回溯:

/usr/lib/python3/dist-packages/sqlalchemy/orm/collections.py in append(self, item, _sa_initiator) 
    1072   def append(self, item, _sa_initiator=None): 
    1073    item = __set(self, item, _sa_initiator) 
-> 1074    fn(self, item) 
    1075   _tidy(append) 
    1076   return append 

/usr/lib/python3/dist-packages/sortedcontainers/sortedlist.py in append(self, val) 
    1026   if val < _lists[pos][-1]: 
    1027    msg = '{0} not in sort order at index {1}'.format(repr(val), self._len) 
-> 1028    raise ValueError(msg) 
    1029 
    1030   _maxes[pos] = val 

很顯然,我們呼籲SortedListappend。如果該值違反排序順序,則從documentation,append引發ValueError。

基本上解決辦法是重寫方法:

class SuperSortedList(SortedList): 
    def append(self, item): 
     self.add(item) 

這似乎甚至在我的現實生活中的例子工作。但是,重寫所有這類方法(例如insert)可能是一個好主意。