将django模型中的保存方法重写为使用芹菜异步的最佳实践



我正在构建一个云系统,我有两个应用程序,包括全部功能的服务器应用程序和仅包括输入法的客户端应用程序,所以我在客户分支机构安装客户端应用程序作为本地应用程序

我想在本地保存模型后覆盖应用程序中的任何模型,我会调用芹菜任务将此模型添加到队列中,以确保它会到达,即使互联网关闭,我也会重试,直到互联网恢复正常,

现在,我希望最佳实践有一种通用的方法来对任何型号的进行操作

我有两个选项

1-覆盖像这样的保存方法

def save(self, *args, **kwargs):
super(Model, self).save(*args, **kwargs)
save_task.delay(self)

或者使用类似的信号

post_save.connect(save-task.delay, sender=Model)

哪一个是最佳实践,我可以使它成为该项目所有模型的泛型?

.save()只是一堆接一堆执行的信号。以下是文档中流程的缩短版本:

  1. 发出预保存信号[…]

  2. 预处理数据[…]大多数字段不进行预处理[…]仅用于具有特殊行为的字段[…]文档中还没有包含包含此项的所有字段的列表"特殊行为。">

  3. 为数据库准备数据要求每个字段以可写入的数据类型提供其当前值数据库大多数字段不需要数据准备[…]整数和字符串"准备写入"作为Python对象[…]复杂的数据类型需要进行一些修改。[…]

  4. 将数据插入数据库[…]

  5. 发出保存后信号[…]

在您的情况下,您没有在该过程中做任何事情。您只需要在模型已经保存之后执行此操作。所以没有必要使用信号。

现在你真正要问的是,如何确保任务最终会被执行。井:

  1. 我相信你可以用芹菜解决这个问题
  2. 你应该将应用程序连接到一个数据库(如果可以的话),不要在本地保存东西,然后更新服务器,这可能会变得很糟糕

但是,如果你真的认为互联网有相当大的可能瘫痪或类似的事情,并且你确信没有更好的方法来链接你的应用程序,我建议你添加一个新的模型来跟踪更新的内容。类似这样的东西:

class Track(models.Model):
modelname = models.CharField(max_length=20)
f_pk = models.IntegerField()
sent = models.BooleanField()
def get_obj(self):
try:
# we want to do modelname.objects.get(pk=self.f_pk), so:
return getattr( getattr(self.modelname, 'objects'), 'get')(pk=self.f_pk)
except:
return False

请注意,我并没有把它链接到某个模型上,而是给它一些工具来获取任何模型。然后,对于你想要跟踪的每个模型,你添加以下内容:

class myModel(models.Model):
...
def save(self, *args, **kwargs):
super(Model, self).save(*args, **kwargs)
t = Track(modelname=self.__class__.__name__, f_pk=self.pk, sent=False)
t.save()

然后用sent=False调度一个将Track对象的任务,并尝试保存它们:

unsent = Track.objects.filter(sent=False)
for t in unsent:
obj = t.get_obj()
# check if this object exists on the server too
# if so:
t.sent = True
t.save()

p.s.

还记得我说过事情会变得丑陋吗?我发布这篇文章已经有好几分钟了,我已经明白了。请注意,我是如何使用pk和modelname来确定模型是否同时保存在这两个位置的,对吧但是,pk是(在django中默认情况下)一个自动递增的字段。如果应用程序在两个地方运行,或者即使您在本地运行它,但出现了一次错误,pks可能很快就会不同步。

假设我保存了一个对象,它在本地和服务器上的pk都为1。

local             server
name    pk   ++   name    pk
obj1    1    ++   obj1    1

然后我又存了一个,但互联网坏了。

local             server
name    pk   ++   name    pk
obj1    1    ++   obj1    1
obj2    2    ++

下次启动时,我会添加一个新对象,但这发生在计划任务运行之前。所以现在我的本地数据库有3个对象,我的服务器有2个,它们有不同的pk,明白吗?

local             server
name    pk   ++   name    pk
obj1    1    ++   obj1    1
obj2    2    ++   obj3    2
obj3    3    ++

在计划的任务运行后,我们将得到:

local             server
name    pk   ++   name    pk
obj1    1    ++   obj1    1
obj2    2    ++   obj3    2
obj3    3    ++   obj2    3

看看这有多容易失控?为了解决这个问题,每个被跟踪的模型都有一个独特的标识符,你需要告诉Track模型如何遵循它。这很头疼。最好不要在本地保存东西,而是将所有东西连接在一起

相关内容

  • 没有找到相关文章

最新更新