Python Cellery在将my queryset obj作为参数传递时引发错误

Python Cellery在将my queryset obj作为参数传递时引发错误,python,django,postgresql,django-rest-framework,celery,Python,Django,Postgresql,Django Rest Framework,Celery,我试图执行一个周期性任务,所以我使用芹菜和Django 1.8、Django Rest框架以及Postgres作为数据库。当我尝试将obj发送到任务时,我得到TypeError:foreign_model_obj不是JSON可序列化的。如何将queryset对象传递给任务 views.py: @celery_app.task(name="my_celery_task") def my_celery_task(querystr): my_model_objs = MyModel.objec

我试图执行一个周期性任务,所以我使用芹菜和Django 1.8、Django Rest框架以及Postgres作为数据库。当我尝试将obj发送到任务时,我得到
TypeError:foreign_model_obj不是JSON可序列化的
。如何将queryset对象传递给任务

views.py:

@celery_app.task(name="my_celery_task")
def my_celery_task(querystr):
    my_model_objs = MyModel.objects.all()
    my_model_objs.query = pickle.loads(querystr) # Restore the queryset
    # ... updating obj attributes
    item=my_model_objs[0]
类MyModelCreateApiView(泛型.CreateAPIView):
queryset=MyModel.objects.all()
serializer\u class=MyModelSerializer
身份验证\类=(令牌身份验证)
def创建(self、request、*args、**kwargs):
数据=dict()
数据['foreign_model_id']=kwargs['pk']
foreign\u model\u obj=MyForeignModel.objects.get(id=data['foreign\u model\u id'])
obj=MyModel.objects.create(**数据)
result=serialize_查询(MyModel,{“id”:obj.id})
本地时间=外国模式时间
我的芹菜任务。应用异步([foreign\u model\u obj],eta=本地时间)
返回响应(结果)
tasks.py:

@celery_app.task(name="my_celery_task")
def my_celery_task(querystr):
    my_model_objs = MyModel.objects.all()
    my_model_objs.query = pickle.loads(querystr) # Restore the queryset
    # ... updating obj attributes
    item=my_model_objs[0]
@cellery\u应用程序任务(name=“my\u cellery\u task”)
定义my_first_芹菜任务(mymodel_obj):
# ... 更新obj属性
mymodel_对象保存()

您只需发送实例的
id
,然后检索任务中的对象即可。 通过这个实例是一种不好的做法,因为它可以同时被修改,特别是你在执行你的任务时看起来像是一个deplay

views.py:

@celery_app.task(name="my_celery_task")
def my_celery_task(querystr):
    my_model_objs = MyModel.objects.all()
    my_model_objs.query = pickle.loads(querystr) # Restore the queryset
    # ... updating obj attributes
    item=my_model_objs[0]
类MyModelCreateApiView(泛型.CreateAPIView):
queryset=MyModel.objects.all()
serializer\u class=MyModelSerializer
身份验证\类=(令牌身份验证)
def创建(self、request、*args、**kwargs):
数据=dict()
数据['foreign_model_id']=kwargs['pk']
foreign\u model\u obj=MyForeignModel.objects.get(id=data['foreign\u model\u id'])
obj=MyModel.objects.create(**数据)
result=serialize_查询(MyModel,{“id”:obj.id})
本地时间=外国模式时间
my_Cellery_task.apply_async([foreign_model_obj.id],eta=本地时间)#只发送obj id
返回响应(结果)
tasks.py:

@celery_app.task(name="my_celery_task")
def my_celery_task(querystr):
    my_model_objs = MyModel.objects.all()
    my_model_objs.query = pickle.loads(querystr) # Restore the queryset
    # ... updating obj attributes
    item=my_model_objs[0]
@cellery\u应用程序任务(name=“my\u cellery\u task”)
定义我的芹菜任务(我的模型对象id):
my_model_obj=MyModel.objects.get(id=MyModel_obj_id)#在这里检索您的对象
# ... 更新obj属性
mymodel_对象保存()

您可以将序列化方法更改为pickle,但不建议将queryset作为参数传递。引自芹菜文献:

另一个问题是Django模型对象。它们不应该作为参数传递给任务。在任务运行时从数据库中重新获取对象几乎总是更好的,因为使用旧数据可能会导致争用情况


实际上,最好的方法是获取查询集的可拾取组件,然后在任务()中重新生成查询集:

任务:

@celery_app.task(name="my_celery_task")
def my_celery_task(querystr):
    my_model_objs = MyModel.objects.all()
    my_model_objs.query = pickle.loads(querystr) # Restore the queryset
    # ... updating obj attributes
    item=my_model_objs[0]

我认为这是最好的方法,因为查询将在任务中执行(可能是第一次执行),避免了各种计时问题,因此不需要在调用者中执行查询(因此不需要在查询中加倍)

太好了,对我有用。我理解它,所以最好避免将queryset实例作为参数发送。可以这样做吗?我的意思是,每次我尝试从tasks.py导入模型时,我都会得到一个importer或从函数中导入它。您可能需要模型模块导入任务模块,任务模块导入模型模块。那不行。但是,在任务模块中,让它在函数中导入模型模块-此时模型已经加载,您不应该有问题。