如何解开Django模型

时间:2017-01-18 13:07:07

标签: django

我有一个名为Chat的模型,可以像这样存储和检索自己的cookie:

>>> chat = Chat.objects.get(pk=43265)
>>> chat.cookies
>>> chat.set_cookie('1','2')
>>> chat.cookies
'{"1": "2"}'

set_cookies方法是使用简单的json.dumps

实现的
def set_cookie(self, key, value):
    if self.cookies:
        current_cookies = json.loads(self.cookies)
    else:
        current_cookies = dict()
    current_cookies.update({key: value})
    self.cookies = json.dumps(current_cookies)
    self.save()

问题是如果在两个不同的命名空间中检索chat对象,它们会独立更新其cookie,每个都会覆盖另一个的结果。

示例:

import django
django.setup()

from bots.models import Chat

# Let's clean all the cookies beforehand 
c = Chat.objects.get(pk=43265)
c.cookies = None
c.save()

def outer_namespace():
    chat = Chat.objects.get(pk=43265)

    # here chat.cookies are empty
    inner_namespace()
    # Now we are supposed to have inner cookie here - right? Let's set another one.

    chat.set_cookie('outer namespace cookie', '1')

    # Let's retrieve the model again and see
    print(Chat.objects.get(pk=43265).cookies)


def inner_namespace():
    inner_chat = Chat.objects.get(pk=43265)
    inner_chat.set_cookie('inner namespace cookie', '2')


outer_namespace()

如果我这样做,我会得到:

>>> {"outer namespace cookie": "1"}
>>> # we lost one of the cookies!

如何避免这种情况? 我想出的唯一解决方案是在其自己的chat方法中间重新检索set_cookies对象。但这看起来很笨拙。

def set_cookie(self, key, value):
    cookies = self.__class__.objects.get(pk=self.pk).cookies
    #
    # ... rest of the method stays the same

1 个答案:

答案 0 :(得分:2)

另一个经典的例子,为什么你应该始终规范化你的数据库。您理想的结构应该是为聊天cookie设置另一个模型

class Cookie(models.Model):
    name = models.CharField()
    value = models.CharField()
    chat = models.ForeignKey(Chat)

现在,您可以使用查询集上的.update方法更新字段而不破坏其他字段。在您自己的线程或其他线程中设置。在每次保存之前,您不必一直重新读取数据。

如果由于某些令人信服的原因您无法将您的设计转换为正确的设计,您至少应该投资使用JsonField作为您的Cookie。 JSONField目前仅适用于postgresql,但有其他dbs的第三方插件。