我正在使用GAE和memcache。对于我的书籍列表,我创建了一个密钥并将其存储在memcache中,以便每次都必须查看列表时避免使用命中数据库。
当我向数据库添加一个新项目时,我也将它添加到memcache键,但是列表的开头,就像这样(在这种情况下,self是书本实体):
class Book(ndb.Model):
""" A Book """
title = ndb.StringProperty(required=True)
author = ndb.StringProperty(required=True)
# Add a new element to memcache
def add_to_memcache(self):
data = memcache.get('mybooks')
if data:
logging.info('Adding to Memcache for key %s.', 'mybooks')
data.insert(0, self)
if not memcache.set('mybooks', data):
logging.error('Memcache set failed for key %s.', 'mybooks')
@classmethod
def get_all(cls):
key = 'mybooks'
books = memcache.get(key)
if books is None:
books = list(Book.query().order(Book.title).fetch(100))
if not memcache.set(key, books):
logging.error('Memcache set failed for key %s.', key)
else:
logging.info('Memcache hit for key %s.', key)
return books
@classmethod
def save(cls, **kwargs):
book = cls(title=kwargs['title'],
author=kwargs['author']
)
book.put()
# Modify memcache for this key
book.add_to_memcache()
return book
所以,在第一次阅读memcache时,所有内容都是有序的,但是有了一本新书,这个列表就不再订购了。
我试图制作:
data.insert(0, self)
data = sorted(data, key=itemgetter(1))
但我收到错误 TypeError:'Book'对象不支持索引
有关索引的任何建议吗?
答案 0 :(得分:1)
这里问题的最终解决方案可能对其他一些"堆栈器"有用。 关键是行
data = sorted(data, key=lambda self: self.key_func())
将从数据列表中获取每个项目(使用lambda函数)并调用key_func,它将评估对象类型以按右侧字段排序。 感谢@root提供此解决方案。
class Book(ndb.Model):
""" A Book """
title = ndb.StringProperty(required=True)
author = ndb.StringProperty(required=True)
def key_func(obj):
if isinstance(obj, Book):
return obj.title
else:
raise TypeError('Unknown object!!!')
# Add a new element to memcache
def add_to_memcache(self):
data = memcache.get('mybooks')
if data:
logging.info('Adding to Memcache for key %s.', 'mybooks')
data.insert(0, self)
data = sorted(data, key=lambda self: self.key_func())
if not memcache.set('mybooks', data):
logging.error('Memcache set failed for key %s.', 'mybooks')
@classmethod
def get_all(cls):
key = 'mybooks'
books = memcache.get(key)
if books is None:
books = list(Book.query().order(Book.title).fetch(100))
if not memcache.set(key, books):
logging.error('Memcache set failed for key %s.', key)
else:
logging.info('Memcache hit for key %s.', key)
return books
@classmethod
def save(cls, **kwargs):
book = cls(title=kwargs['title'],
author=kwargs['author']
)
book.put()
# Modify memcache for this key
book.add_to_memcache()
return book
注意:add_to_memcache函数旨在在多个类中共享,但我已将其放在Book中仅供查询。
答案 1 :(得分:0)
免责声明:我对GAE了解不多,所以这个答案纯粹是关于排序。
首先,如果没有实现operator.itemgetter
方法,则无法直接使用__getitem__
访问类属性,因为类基本上是字典 - 所以它的属性不是有序的。
示例:的
In [1]: from random import shuffle
In [2]: from operator import itemgetter
In [3]: rand = range(10)
In [4]: shuffle(rand)
In [5]: rand
Out[5]: [1, 9, 2, 5, 4, 3, 0, 6, 8, 7]
In [6]: class A(object):
...: def __init__(self, n):
...: self.n = n
...: def __repr__(self):
...: return str(self.n)
...:
In [7]: sorted([A(n) for n in rand], key=itemgetter(0))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-33ca678e282d> in <module>()
----> 1 sorted([A(n) for n in rand], key=itemgetter(0))
TypeError: 'A' object does not support indexing
In [8]: class A(object):
...: def __init__(self, n):
...: self.n = n
...: def __repr__(self):
...: return str(self.n)
...: def __getitem__(self,ind):
...: return self.n
...:
In [9]: sorted([A(n) for n in rand], key=itemgetter(0))
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
但也许你有更好的选择:
您可以使用operator.attrgetter
;对于Book
个实例(按标题排序),这将是:
sorted(data, operator.attrgetter('title'))
您可以编写更通用的键功能进行排序:
def key_func(obj):
if isinstance(obj, Book):
return obj.title
elif isinstance(obj, SomeOtherClass):
return obj.some_other_attr
else:
raise TypeError('Unknown object!!!')
# usage: sorted(data, key=key_func)
或者您可以为每个类实现__cmp__
方法,因此排序可以在没有的情况下工作
关键功能:
def __cmp__(self, other):
return cmp(self.attribute_you_want_to_be_compared, other)
示例:的
In [10]: class A(object):
...: def __init__(self, n):
...: self.n = n
...: def __repr__(self):
...: return str(self.n)
...: def __cmp__(self, other):
...: return cmp(self.n, other)
...:
In [11]: sorted([A(n) for n in rand])
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]