2013-03-26 97 views
0

對不起,我想不出一個更好的通用標題。我正在使用金字塔和sqlalchemy構建一個照片投票應用程序。完整的模式和ORM是在最後,但最相關的信息是查詢其他表進一步鏈接的一對多關係

  1. photo
  2. votephoto_iduser_id,後者標識或者誰投贊成票上下照片中的用戶。
  3. category表照片分類列表
  4. photocategory臺聯photocategory

在應用程序的主照片供稿我想顯示的照片按以下順序

  1. 用戶未投票的照片,他/她已投票
  2. 以上各組內(未投票和ñ投票),排序下降的照片

該應用程序的現有投票數的順序也將可以靈活地顯示某些品類只有

我現在實現的方式是照片...

  • 只獲得了照片所需的類別

photos = DBSession.query(Photos).join(photocategory, Photo.id==photocategory.c.photo_id).filter(photocategory.c.category_id==__CATEGORY_ID_HERE__).all() 
  • 通過投票

photos = sorted(photos, key=lambda photo: len(photo.votes), reverse=True) 
  • 通過photos迭代次數排序photos來查看用戶是否已經投票,和照片添加到任何一個votedunvoted list/array

但是,這是如此低效,因爲我必須搜索用戶以前投過的所有照片,因爲我在photos的每張照片中都有投票,所以我想知道什麼是正確和有效的方法來做到這一點......謝謝

SCHEMA

photo_table = schema.Table('photo', metadata, 
    schema.Column('id', types.Integer, 
    schema.Sequence('photo_seq_id'), primary_key=True), 
    schema.Column('caption', types.UnicodeText(), nullable=True), 
    schema.Column('timestamp', types.TIMESTAMP(), default=datetime.now()), 
    schema.Column('last_updated', types.TIMESTAMP(), default=datetime.now(),), 
    schema.Column('spam', types.Boolean, default=0), 
    schema.Column('trash', types.Boolean, default=0), 
    schema.Column('image_path', types.Unicode(255), nullable=False), 
    schema.Column('user_id', types.Integer, schema.ForeignKey('user.id', ondelete='CASCADE')), 
    mysql_engine='InnoDB' 
) 

category_table = schema.Table('category', metadata, 
    schema.Column('id', types.Integer, 
    schema.Sequence('category_seq_id'), primary_key=True), 
    schema.Column('name', types.Unicode(255), nullable=False, unique=True), 
    mysql_engine='InnoDB' 
) 

photocategory_table = schema.Table('photocategory', metadata, 
    schema.Column('photo_id', types.Integer, schema.ForeignKey('photo.id', ondelete='CASCADE'), primary_key=True), 
    schema.Column('category_id', types.Integer, schema.ForeignKey('category.id', ondelete='CASCADE'), primary_key=True), 
    mysql_engine='InnoDB' 
) 

vote_table = schema.Table('vote', metadata, 
    schema.Column('id', types.Integer, 
    schema.Sequence('vote_seq_id'), primary_key=True), 
    schema.Column('timestamp', types.TIMESTAMP(), default=datetime.now()), 
    schema.Column('upvote', types.Boolean, nullable=False), 
    schema.Column('photo_id', types.Integer, schema.ForeignKey('photo.id', ondelete='CASCADE')), 
    schema.Column('user_id', types.Integer, schema.ForeignKey('user.id', ondelete='CASCADE')), 
    mysql_engine='InnoDB' 
) 

ORM映射

orm.mapper(Photo, photo_table, properties={ 
    'votes': orm.relation(Vote, backref='photo', lazy='dynamic'), 
    'categories': orm.relation(Category, secondary=photocategory_table, backref='photos'), 
}) 

orm.mapper(User, user_table, properties={ 
    'photos': orm.relation(Photo, backref='owner'), 
    'votes': orm.relation(Vote, backref='voter', lazy='dynamic'), 
}) 

回答

0

也許d使用SQL本身是一個更好的主意。以下是未經測試,將可能無法正常工作,但你可以調整它來滿足您的需求

您可以通過

cat_photos = session.query(PhotoCategory.photo_id.label('pid')).options(lazyload('*')).filter(PhotoCategory.category_id==SOMEID).subquery() 

加入用戶和照片表中選擇一個類別的照片得到的照片列表用戶可以在其上投票。假設用戶在自己的照片不能投票,你會得到

elig_photos = session.query(User).join(Photos,Photos.user_id!=User.id).options(lazyload('*')).with_entities(Photos.id.label('pid'),User.id.label('uid').subquery() 

現在你可以離開加入這票表和你的子查詢,以獲得該用戶尚未投票

特定類別的照片
not_voted = session.query(elig_photos).outerjoin(Votes,and_(Votes.photo_id==elig_photos.c.pid,Votes.user_id==elig_photos.c.uid)).join(cat_photos,cat_photos.c.pid==elig_photos.c.pid).with_entities(elig_photos.c.pid.label('photo_id'),Votes.upvote.label('upvote')).options(lazyload('*')).filter(User.id==SOMEUSER).filter(Votes.upvote==None).all() 

獲取此類別上的照片以票數排序。我們將不得不做一個左連接,因爲可能有一些照片,沒有人投了贊成票尚未

sorted_votes = session.query(cat_photos).outerjoin(Votes,cat_photos.c.pid==Votes.photo_id).with_entities(cat_photos.c.pid.label('pid'),func.coalesce(func.sum(Votes.upvote),0).label('sum_votes')).options(lazyload('*')).group_by(cat_photos.pid).order_by(desc('sum_votes')).all() 

注 - 我增加了一個-a選項options(lazyload('*'))每個查詢,使關係懶加載現在

你有兩個列表 -

  • sorted_votes其中列出了該類別的照片降序 爲了投票(0票照片還沒有被評爲任何人)
  • not_voted其中列出了該類別的照片不是由用戶進行表決

注意,這個類別由用戶上傳的照片將是第一個列表的一部分

您可以處理蟒蛇兩個列表顯示not_voted首先基於其索引中第一個列表,然後顯示第一個列表的其餘部分,因爲它是

not_voted_sorted = sorted(not_voted,key=lambda x:sorted_votes.index(x)) 
rest_of_the_photos = [y for y in sorted_votes if y not in not_voted] 

這將是一個不錯的主意(IMO),如果你只能從這些查詢的photo_ids。整個照片對象列表可以從數據庫中分開提取並保存在一個字典中,其中photo_id是關鍵字。因此,如果您知道您不想顯示的photo_id,則可以在模板中顯示整個照片的詳細信息。

Final注意:如果某些內容不起作用,請嘗試爲您正在嘗試的操作編寫普通SQL,然後編寫SQLAlchemy等效項並打印語句以比較手寫SQL和SQLAlchemy生成的SQL是否爲相同或不相同

相關問題