Python 如何向google数据存储StringListProperty添加选项?

Python 如何向google数据存储StringListProperty添加选项?,python,google-app-engine,google-cloud-datastore,webapp2,Python,Google App Engine,Google Cloud Datastore,Webapp2,好的,问题出在这里。我有这个密码 list_categories = [None,"mathematics","engineering","science","other"] class Books(db.Model) title = db.StringProperty(required=True) author = db.StringProperty() isbn = db.StringProperty() categories = db.StringListP

好的,问题出在这里。我有这个密码

list_categories = [None,"mathematics","engineering","science","other"]
class Books(db.Model)
    title = db.StringProperty(required=True)
    author = db.StringProperty()
    isbn = db.StringProperty()
    categories = db.StringListProperty(default=None, choices = set(list_categories))
我想在这里做的是让我的书。例如,类别是列表类别的子集 我有一本书,它的分类应该是“工程学”和“数学”,但当我

book.categories = ['engineering','mathematics']
它webapp2给了我一个错误

BadValueError: Property categories is ['engineering','mathematics']; must be one of set([None,"mathematics","engineering","science","other"])
我在这里的初步猜测是,我必须将我的列表选择设置为[None]、“mathematics”、“engineering”、“science”、“other”]的POWERSET,但这太低效了

有人知道这方面的解决方法吗?

错误的原因(我相信你已经猜到了)是
StringListProperty
没有对
choices
关键字参数进行任何特殊处理-它只是将其传递给
ListProperty
构造函数,然后将其传递给
属性
构造函数,在那里对其进行评估:

if self.empty(value):
    if self.required:
        raise BadValueError('Property %s is required' % self.name)
    else:
      if self.choices:
        match = False
        for choice in self.choices:
          if choice == value:
            match = True
        if not match:
          raise BadValueError('Property %s is %r; must be one of %r' %
                              (self.name, value, self.choices))
问题是,它会逐个迭代每个
选项
,但会将其与整个列表(
)进行比较,这将永远不会导致匹配,因为字符串不等于列表(同样,您知道:)

我的建议是修改将列表分配给属性的方式。例如,而不是:

book.categories = ['engineering','mathematics']
试着这样做:

for category in ['engineering','mathematics']:
    book.categories.append(category)
由于
ListProperty
包含一个列表,因此可以单独追加每个项目,以便通过前面代码中的测试。请注意,为了在我的测试中实现这一点,我必须以一种稍微不同的方式设置模型-但是如果您能够得到上面提到的错误,那么
append
方法应该可以正常工作


我同意,这让它变得不那么直截了当,但它应该能够避免上述问题,并有望奏效。

使用键列表创建多对多关系。使用
class Book
中的
categories
属性作为
class Category
的键列表

class Book(db.Model)
    title = db.StringProperty(required=True)
    author = db.StringProperty()
    isbn = db.StringProperty()

    # List Of Keys
    categories = db.ListProperty(db.Key)

class Category(db.Model)
    name = db.StringProperty(choices = ('science', 'engineering', 'math'))
有关建模的更多信息和代码示例,请查看: