M
M
Mikhail2019-09-28 14:32:05
Celery
Mikhail, 2019-09-28 14:32:05

Async function causes 'is not JSON serializable' error?

There is view.py

from rest_framework.response import Response
from rest_framework.views import APIView
from .models import *
from .tasks import trasactiontaskfunc
#from .trasactionfunc import trasactionfunc

# Create your views here.
class PageView(APIView):
    def get(self, request, item):
        page = Page.objects.filter(pk=item).first()
        
        totrasaction = []
        
        la = []
        for e in page.pageaudio_set.all():
            el = {
                  'type': 'audio',
                  'id': e.audio.pk,
                  'title': e.audio.title,
                  'counter': e.audio.counter,
                  'bitrate': e.audio.bitrate,
                  }
            totrasaction.append(e.audio)
            la.append({'order': e.order, 'quantity': e.quantity, 'el': el})
        lv = []
        for e in page.pagevideo_set.all():
            el = {
                  'type': 'video',
                  'id': e.video.pk,
                  'title': e.video.title,
                  'counter': e.video.counter,
                  'fileurl': e.video.fileurl,
                  'subtitresurl': e.video.subtitresurl
                  }
            totrasaction.append(e.video)
            lv.append({'order': e.order, 'quantity': e.quantity, 'el': el})
        lt = []
        for e in page.pagetext_set.all():
            el = {
                  'type': 'text',
                  'id': e.text.pk,
                  'title': e.text.title,
                  'counter': e.text.counter,
                  'text': e.text.text,
                  }
            totrasaction.append(e.text)
            lt.append({'order': e.order, 'quantity': e.quantity, 'el': el})
        
        content = {
            "id": item,
            "title": page.title,
            "pageaudio": la,
            "pagevideo": lv,
            "pagetext": lt,
                   }
        
        trasactiontaskfunc.delay(totrasaction)
        #trasactionfunc(totrasaction)
        
        return Response({'t':1})

There are tasks:
from celery import shared_task
from api.trasactionfunc import trasactionfunc

@shared_task(time_limit=20000)
def trasactiontaskfunc(totrasaction):
    return trasactionfunc(totrasaction)

Transaction:
from django.db import transaction

def trasactionfunc(totrasaction):
    try:
        with transaction.atomic():
            for e in totrasaction:
                e.counter = e.counter + 1
                e.save()
    except:
        transaction.rollback()
    else:
        return True
    return False

Why do I get the response:
EncodeError at /api/page/1
is not JSON serializable
If the function is asynchronous and there is no return at all? If I do it directly, without celery, then there are no errors at all...

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Gornostaev, 2019-09-28
@lightarhont

I categorically do not understand why you are increasing counters in a cycle, especially in an asynchronous task. Correctly it is done like this:
But if you really want to do it in an asynchronous task for some reason, then it’s better like this:

trasactiontaskfunc.delay({
    'audio': list(page.pageaudio_set.values_list('id', flat=True)),
    'video': list(page.pagevideo_set.values_list('id', flat=True)),
    'text': list(page.pagetext_set.values_list('id', flat=True)),
})

def trasactionfunc(totrasaction):
    try:
        with transaction.atomic():
            Audio.objects.filter(id__in=totrasaction['audio']).update(counter=F('counter ') + 1)
            Video.objects.filter(id__in=totrasaction['video']).update(counter=F('counter ') + 1)
            Text.objects.filter(id__in=totrasaction['text']).update(counter=F('counter ') + 1)
    except:
        transaction.rollback()
    else:
        return True
    return False

Better yet, make it Contentnon-abstract and pass identifiers as a simple list.
PS You don't need to explicitly roll back the transaction, the context manager does it for you.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question