【问题标题】:'Model is not immutable' TypeError'模型不是不可变的' TypeError
【发布时间】:2013-09-13 19:37:47
【问题描述】:

我正在获取此回溯;

--- Trimmed parts ---
File "C:\Users\muhammed\Desktop\gifdatabase\gifdatabase.py", line 76, in maketransaction
    gif.tags = list(set(gif.tags + tags))
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\ndb\model.py", line 2893, in __hash__
    raise TypeError('Model is not immutable')
TypeError: Model is not immutable

这是我的代码的相关部分;

class Gif(ndb.Model):
    author = ndb.UserProperty()
    #tags = ndb.StringProperty(repeated=True)
    tags = ndb.KeyProperty(repeated=True)

    @classmethod
    def get_by_tag(cls,tag_name):
        return cls.query(cls.tags == ndb.Key(Tag, tag_name)).fetch()

class Tag(ndb.Model):
    gif_count = ndb.IntegerProperty()

class PostGif(webapp2.RequestHandler):

    def post(self):

        user = users.get_current_user()
        if user is None:
            self.redirect(users.create_login_url("/static/submit.html"))
            return

        link = self.request.get('gif_link')
        tag_names = shlex.split(self.request.get('tags').lower())


        @ndb.transactional(xg=True)
        def maketransaction():
            tags = [Tag.get_or_insert(tag_name) for tag_name in tag_names]
            gif = Gif.get_or_insert(link)

            if not gif.author: # first time submission
                gif.author = user

            gif.tags = list(set(gif.tags + tags))
            gif.put()
            for tag in tags:
                tag.gif_count += 1
                tag.put()

        if validate_link(link) and tag_names:
            maketransaction()
            self.redirect('/static/submit_successful.html')
        else:
            self.redirect('/static/submit_fail.html')

gif.tags = list(set(gif.tags + tags)) 线路有什么问题?

【问题讨论】:

    标签: google-app-engine python-2.7 app-engine-ndb


    【解决方案1】:

    您正在插入标签而不是键,您需要访问

    tags = [Tag.get_or_insert(tag_name).key .....]
    

    但您也可以像这样将其设为单个网络跃点

    futures = [Tag.get_or_insert_async(tag_name) for tag_name in tag_names]
    futures.append(Gif.get_or_insert_async(link))
    ndb.Future.wait_all(futures)
    gif = futures.pop().get_result()
    tags = [future.get_result() for future in futures]
    

    但这并不是真正的问题,只是一个建议 ^,使用 .key 更清晰的答案是

    gif.tags = gif.tags + [tag.key for tag in tags]
    # or 
    gif.tags.extend([tag.key for tag in tags])
    

    【讨论】:

    • 非常感谢。你对我的 gae 问题很有帮助:)
    • 不客气。作为附加提示,大多数 ndb 方法都像 _async 一样,您始终可以建立期货以避免网络跃点,甚至通过 ndb.get_context() 甚至 memcache 和 urlfetch 以便 ndb 将尝试自动批处理这些请求以使它们成为小型网络尽可能跳。
    猜你喜欢
    • 1970-01-01
    • 2014-08-05
    • 2017-09-05
    • 2018-05-24
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 2016-03-16
    • 2017-09-15
    相关资源
    最近更新 更多