moh*_*ohd 0 django message-queue django-models celery django-celery
我正在建立一个云系统,我有两个应用程序,包括完整功能的服务器应用程序,以及仅包含输入法的客户端应用程序,所以我在客户分支中安装客户端应用程序作为本地应用程序,
我希望在本地保存模型后覆盖应用程序中的任何模型,我将调用芹菜任务将此模型添加到队列中以确保它将到达,即使互联网已关闭,我将重试直到互联网起步,
现在我希望最佳实践能够以通用的方式对任何模型进行操作
我有两个选择
1-这样的覆盖保存方法
def save(self, *args, **kwargs):
super(Model, self).save(*args, **kwargs)
save_task.delay(self)
Run Code Online (Sandbox Code Playgroud)
或使用这样的信号
post_save.connect(save-task.delay, sender=Model)
Run Code Online (Sandbox Code Playgroud)
哪一个是最佳实践,我可以为这个项目的所有模型制作泛型?
.save()只是一堆一个接一个地执行的信号.这是文档中流程的缩短版本:
发出预保存信号.[...]
预处理数据.[...]大多数字段不进行预处理[...]仅用于具有特殊行为的字段[...]文档尚未包含具有此"特殊行为"的所有字段的列表.
准备数据库的数据.要求每个字段以可写入数据库的数据类型提供其当前值.大多数字段不需要数据准备[...]整数和字符串'准备写'作为Python对象[...]复杂的数据类型通常需要一些修改.[...]
将数据插入数据库.[...]
发出保存后信号.[...]
在您的情况下,您在该过程的中间没有做任何事情.您只需在保存模型后执行此操作.所以不需要使用信号.
现在您真正要问的是如何确保最终执行任务.好:
但是,如果你真的认为互联网发生故障的可能性很大,或者你确定没有更好的方式来链接你的应用程序,我建议你添加一个新的模型来跟踪已经更新的内容.像这样的东西:
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
Run Code Online (Sandbox Code Playgroud)
请注意我是如何将它链接到某个模型,而是给它提供工具来获取你该死的任何模型.然后,对于要跟踪的每个模型,添加以下内容:
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()
Run Code Online (Sandbox Code Playgroud)
然后调度将Track与对象对齐的任务sent=False并尝试保存它们:
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()
Run Code Online (Sandbox Code Playgroud)
PS
还记得我提到的事情会变得难看吗?自从我发布这个以来,我已经看到了.请注意我如何使用pk和modelname来确定是否在两个地方都保存了模型,对吧?但是,pk是(默认情况下在django中)一个自动递增的字段.如果应用程序在两个地方运行,或者即使你在本地运行它并且发生了一次错误,那么pks很快就会失去同步.
假设我保存了一次对象,它在本地和服务器上获得了1的pk.
local server
name pk ++ name pk
obj1 1 ++ obj1 1
Run Code Online (Sandbox Code Playgroud)
然后我保存另一个,但互联网下降.
local server
name pk ++ name pk
obj1 1 ++ obj1 1
obj2 2 ++
Run Code Online (Sandbox Code Playgroud)
下次启动时,我会添加一个新对象,但这会在调度任务运行之前发生.所以现在我的本地数据库有3个对象,我的服务器有2个,那些有不同的pk,得到它?
local server
name pk ++ name pk
obj1 1 ++ obj1 1
obj2 2 ++ obj3 2
obj3 3 ++
Run Code Online (Sandbox Code Playgroud)
在调度任务运行后,我们将拥有:
local server
name pk ++ name pk
obj1 1 ++ obj1 1
obj2 2 ++ obj3 2
obj3 3 ++ obj2 3
Run Code Online (Sandbox Code Playgroud)
看看这有多么容易失控?要解决此问题,每个跟踪的模型都必须具有某种唯一标识符,您需要以某种方式告诉Track模型如何遵循它.这很头疼.最好不要在本地保存,而是将所有内容链接在一起
| 归档时间: |
|
| 查看次数: |
1264 次 |
| 最近记录: |