[Solved]-How to send django objects to celery tasks?

9👍

Django objects can’t be sent in celery tasks, you can serialize with django serializers (from django.core import serializers) by providing fields needed in template and the lookup will work like a django object in template

NOTE: with serializer you will need to dump and load the data

or just convert your queryset to a list like the following:

send_daemon_email.delay(
    instance = User.objects.filter(pk=user.pk).values('first_name','last_name'),
    all_courses= list(Course.objects.values('title','other_field'))
)

All you need is to provide fields that you really need in template with values('')

@shared_task
def send_daemon_email(instance,all_courses):
    ctx = {
        'instance': instance,
        'all_courses': all_courses,
    }
    message = get_template("emails/ads.html").render(ctx)

In templates {% for course in all_courses %}{{course}}{% endfor %} will display all the courses, and {{ instance.first_name }} the user

9👍

Well typically tools like celery, use a format to pass messages. Here JSON is used, and not every Python object can, by default, be turned into a JSON object.

We can however for example pass the primary keys, and then turn these in objects again at the receiver side. So for example:

send_daemon_email.delay(
    instance=instance.pk,
    all_courses=list(Course.objects.all().values_list('pk', flat=True))
)

and then at the side of the receiver, we can fetch the objects with:

@shared_task
def send_daemon_email(instance,all_courses):
    ctx = {
        'instance': User.objects.get(pk=instance),
        'all_courses': Course.objects.filter(pk__in=all_courses)
    }
    message = get_template("emails/ads.html").render(ctx)

Of course we do not per se need to pass primary keys: any kind of object that can be JSON serialized (or by manually serializing) can be used. Although I would not make it too complicated, usually simple things work better than more complex (which is one of the credos of Python).

Leave a comment