使用ndb重复查询中的Joes太多

时间:2012-09-06 10:50:44

标签: python google-app-engine

调试我的应用程序时发现了一些意外的行为。有谁知道为什么我得到下面描述的结果?

from google.appengine.ext import ndb

class Person(ndb.Model):
  name = ndb.StringProperty()
  shared = ndb.BooleanProperty(default=False)

class Department(ndb.Model):
  name = ndb.StringProperty()
  persons = ndb.KeyProperty(kind=Person, repeated=True)

  @property
  def all_department_resources(self):    
    emp_list = self.persons
    for p in Person.query().filter(Person.shared == True):
      emp_list.append(p.key)
    return emp_list 

p1 = Person(name='Jane').put()
p2 = Person(name='Siri').put()
p3 = Person(name='Joe', shared=True).put()
Department(name='Finance',persons=[p1,p2]).put()

print '\n*First run*'
for d in Department.query():
  print '>>' + d.name
  for p in d.all_department_resources:   
    print p.get().name

print '\n*Second run:*'
for d in Department.query():
  print '>>' + d.name
  for p in d.all_department_resources:   
    print p.get().name

输出:

*First run*
>>Finance
Jane
Siri
Joe

*Second run:*
>>Finance
Jane
Siri
Joe
Joe

我的问题很简单:第二个Joe来自哪里?

2 个答案:

答案 0 :(得分:3)

all_department_resources中,您将Joe添加到self.persons列表中。在第二个电话中,您再次添加它。您可以通过第三次执行文本块并找到三个Joes来确认此行为....

<强>为什么吗

emp_list = self.persons

不会复制列表,但会引用它。您对emp_list所做的一切都发生在self.persons

我该怎么办? 使用

制作副本
emp_list = list(self.persons)

或者您可以将查询添加到return语句中:

  @property
  def all_department_resources(self):    
    return self.persons + Person.query().filter(Person.shared == True)

答案 1 :(得分:0)

每次执行for p in d.all_department_resources:时都会执行

for p in Person.query().filter(Person.shared == True):
    emp_list.append(p.key)`

在您的Persons列表中添加了Joe的密钥。