我有一个名为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
答案 0 :(得分:2)
另一个经典的例子,为什么你应该始终规范化你的数据库。您理想的结构应该是为聊天cookie设置另一个模型
class Cookie(models.Model):
name = models.CharField()
value = models.CharField()
chat = models.ForeignKey(Chat)
现在,您可以使用查询集上的.update
方法更新字段而不破坏其他字段。在您自己的线程或其他线程中设置。在每次保存之前,您不必一直重新读取数据。
如果由于某些令人信服的原因您无法将您的设计转换为正确的设计,您至少应该投资使用JsonField作为您的Cookie。 JSONField目前仅适用于postgresql,但有其他dbs的第三方插件。