I have a Django app that uses Celery to offload some tasks. Mainly, it defers the computation of some fields in a database table.
So, I have a tasks.py:
from models import MyModel from celery import shared_task @shared_task def my_task(id): qs = MyModel.objects.filter(some_field=id) for record in qs: my_value = #do some computations record.my_field = my_value record.save()
And in models.py
from django.db import models from tasks import my_task class MyModel(models.Model): field1 = models.IntegerField() #more fields my_field = models.FloatField(null=True) @staticmethod def load_from_file(file): #parse file, set fields from file my_task.delay(id)
Now obviously, this won't work because of a circular import (models
imports tasks
and tasks
imports models
).
I've resolved this for the moment by calling my_task.delay()
from views.py
, but it seems to make sense to keep the model logic within the model class. Is there a better way of doing this?
also just as a reference, it seems circular imports are allowed on python 3.5 (and probably beyond) but not 3.4 (and probably bellow).
The solution posted by joshua is very good, but when I first tried it, I found that my @receiver
decorators had no effect. That was because the tasks
module wasn't imported anywhere, which was expected as I used task auto-discovery.
There is, however, another way to decouple tasks.py
from modules.py
. Namely, tasks can be sent by name and they don't have to be evaluated (imported) in the process that sends them:
from django.db import models #from tasks import my_task import celery class MyModel(models.Model): field1 = models.IntegerField() #more fields my_field = models.FloatField(null=True) @staticmethod def load_from_file(file): #parse file, set fields from file #my_task.delay(id) celery.current_app.send_task('myapp.tasks.my_task', (id,))
send_task()
is a method on Celery app objects.
In this solution it is important to take care of correct, predictable names for your tasks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With