David
David

Reputation: 120

Hooking Django model intstance's save method to celery

I am using S3 as a media storage in Django. The thing is, If the video is uploaded it takes too long to return the response in a view. I know there should be a way to make it async.

snippet of view.py

with transaction.atomic():
    media = Media(
        med_user_id=account,
        med_path=file,
        med_thumbnail=thumbnail,
        med_assoc_data=data,
    )

   save_async.delay(media)

variable file is a video with this class<class 'django.core.files.uploadedfile.TemporaryUploadedFile'>

when I am saving this by media.save() it takes 12-20 seconds to complete. I thought to create a celery task that could handle it.

@app.task(bind=True)
def save_async(self, instance):
    instance.save()

I know this doesn't make any sense because it throws a serialization error. Object of type Media is not JSON serializable so the question is. how should I make model.save() function async with celery?

Thank you in advance.

Upvotes: 1

Views: 1067

Answers (1)

devdob
devdob

Reputation: 1504

Celery doesn't understand objects like so. Your best solution is to send the object attributes to the save_async. Yes you will loose the generalization of the your delayed save method. So in this case, you will need to save a reference in the database and send the attributes with the data to the delay method. Example on your above is like so,

in views.py

with transaction.atomic():
    media = Media(
       med_user_id=account,
       med_path=file,
       med_thumbnail=thumbnail,
       med_assoc_data=None,    # you can remove this or add a reference to ur S3 upload ID
   )

media.save()

save_async.delay(media.id, data)

in tasks.py file

@app.task(bind=True)
def save_async(instance_id, data):
    media = Media.objects.get(pk=instance_id)
    media.data = data
    media.save()

Hope this helps!

Upvotes: 1

Related Questions