我有这个数据模型(我做了,所以如果有更好的方法,请告诉我)。
我真的Club
可以有很多Courses
。现在我想知道俱乐部的所有members
和instructors
。 members
和instructors
存储在Course
模型中,Club
有对它们的引用。
见代码..
class Course(ndb.Model):
...
instructor_keys = ndb.KeyProperty(kind="User", repeated=True)
member_keys = ndb.KeyProperty(kind="User", repeated=True)
@property
def instructors(self):
return ndb.get_multi(self.instructor_keys)
@property
def members(self):
return filter(lambda x: x.is_active, ndb.get_multi(self.member_keys))
def add_instructor(self, instructor):
if instructor.key not in self.instructor_keys:
self.instructor_keys.append(instructor.key)
self.put()
def rm_instructor(self, instructor):
if instructor.key in self.instructor_keys:
self.instructor_keys.remove(instructor.key)
self.put()
def add_member(self, member):
if member.key not in self.member_keys:
self.member_keys.append(member.key)
self.put()
def rm_member(self, member):
if member.key in self.member_keys:
self.member_keys.remove(member.key)
self.put()
和
class Club(ndb.Model):
...
owners_keys = ndb.KeyProperty(kind="User", repeated=True)
course_keys = ndb.KeyProperty(kind="Course", repeated=True)
@property
def members(self):
# TODO: is this correct? efficient?
l_members = []
for courses in self.courses:
l_members = l_members + courses.members
return l_members
@property
def trainers(self):
l_trainers = []
for courses in self.courses:
l_trainers = l_trainers + courses.trainers
return l_trainers
@property
def owners(self):
return ndb.get_multi(self.owners_keys)
@property
def courses(self):
return filter(lambda x: x.is_active, ndb.get_multi(self.course_keys))
def add_owner(self, owner):
if owner.key not in self.owners_keys:
self.owner_keys.append(owner.key)
self.put()
def rm_owner(self, owner):
if owner.key in self.owners_keys:
self.owner_keys.remove(owner.key)
self.put()
def add_course(self, course):
if course.key not in self.courses_keys:
self.course_keys.append(course.key)
self.put()
def rm_course(self, course):
if course.key in self.courses_keys:
self.course_keys.remove(course.key)
self.put()
def membership_type(self, user):
if user.key in self.owners_keys:
return "OWNER"
elif user in self.members:
return "MEMBER"
elif user in self.trainers:
return "TRAINER"
else:
raise Exception("The user %s is not in the club %s" % (user.id, self.id))
现在,@property
上的Course
对我来说似乎没问题。 (我对吗?)
但是Club
中的那个似乎非常低效。每次我都要迭代所有Courses
来计算members
和trainers
。此外,这些方法不会被缓存,而是每次都会计算。所以,如果它非常昂贵。
有什么建议吗?
我在考虑将instructors
和members
列为Club
中的密钥列表,并在每次将某人添加到Course
时更新俱乐部,但不确定& #39;是正确的。
PS:还有更好的方法来filter
上的ndb.get_multi
吗?
答案 0 :(得分:1)
我会尝试将您的模型标准化,而不是去取消标准化模型:
class CourseInscription(ndb.Model):
member = ndb.KeyProperty(kind='User', required=True)
course = ndb.KeyProperty(kind='Course', required=True)
is_active = ndb.BooleanProperty(default=True)
然后,您可以添加类似
的内容class Course(ndb.Model):
# all the stuff already there
@property
def members(self):
return CourseInscription.query(CourseInscription.course == self.key)
一般来说,我更喜欢只返回查询,让调用者决定直接调用它或者添加更多的过滤/排序,而不是直接执行 ndb.get_multi 。
我通常做的另一个不错的尝试是使用父母为关系实体构建id,因此我可以使用get by id轻松检查是否存在而不必查询
class CourseInscription(ndb.Model):
# all the other stuff
@staticmethod
def build_id(user_key, course_key):
return '%s/%s' % (user_key.urlsafe(), course_key.urlsafe())
# somewhere I can create an inscription like
CourseInscription(
id=CourseInscription.build_id(user_key, course_key),
user=user_key, course=course_key, is_active=True
).put()
# somewhere else I can check if a User is in a Course by just getting... no queries needed
if ndb.Key(CourseInscription, CourseInscription.build_id(user, course)).get():
# Then the user is in the course!
else:
# then it's not
答案 1 :(得分:1)
除了被课程引用之外,成员和教师都属于俱乐部是完全合理的。考虑到用例,会员在加入俱乐部提供的课程之前需要加入俱乐部(尽管这可能会在同一时间发生)。直接(在俱乐部中)引用成员/教师而不是每次都必须遍历课程也是非常有效的。您的权衡需要额外的代码维护,但在这种情况下这似乎是合理的。
关于有效课程过滤器,您可能希望考虑“有效”课程。课程列表和“不活动”#39;俱乐部的课程列表:一旦不再提供课程,请将其移至“不活动”状态。列表(并从'活动'列表中删除它。)