1

I'm trying to creating a background task with Django celery and Redis as broker. this task is being sent from models when model post save. But the problem is that, the same task is getting executed 1000 of times (other debug or add task are working fine). i have already tried this method but this didn't resolve the issue. Please find the below codes for your reference and help to resolve. Thanks in advance.

models.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from student.tasks import create_student_subject_tryout_result, add

@receiver(post_save, sender=TryoutSubmission, 
dispatch_uid='create_student_subject_tryout_result')
def result_calculation(sender, instance, **kwargs):
    if instance.status == 'C':
       print('Calculating result')
       create_student_subject_tryout_result.delay(instance.student.id, 
       instance.tryout.id)

celery.py

import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eec.settings')

app = Celery('eec')

app.config_from_object('django.conf:settings', namespace='CELERY')
app.conf.broker_transport_options = {'visibility_timeout': 3600} .

app.autodiscover_tasks()


@app.task(bind=True)
def debug_task(self):
    print(f'Request: {self.request!r}')

tasks.py

from celery import shared_task
import tryout.models

@shared_task(bind=True)
def create_student_subject_tryout_result(self, student_id, tryout_id):
    tryout_submission=tryout.models.TryoutSubmission.objects.get(
        student_id=student_id, tryout_id=tryout_id
    )                                                           
    tryout_questions = tryout_submission.tryout.tryoutquestion_set.all().count()
    answered_qs = tryout_submission.tryout.tryoutanswersubmission_set.filter(
            is_answered=True).count() 
    correct_ans = tryout_submission.tryout.tryoutanswersubmission_set.filter(
            is_correct=True).count()
    tryout_submission.total_questions = tryout_questions
    tryout_submission.answered_questions = answered_qs
    tryout_submission.correct_answers = correct_ans
    tryout_submission.total_time = tryout_submission.end_time - tryout_submission.start_time
    tryout_submission.save()
    return "Result created"

settings.py

CELERY_RESULT_BACKEND = 'django-db'
CELERY_CACHE_BACKEND = 'django-cache'
CELERY_BROKER_URL = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Kolkata'
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

1 Answer 1

0

Well, if you look at your receiver, you are listening to post_save on your model.

The post_save signal also supplies a boolean to denote if it was created or not. Instead of checking instance.status == 'C', check for created:

from django.db.models.signals import post_save
from django.dispatch import receiver
from student.tasks import create_student_subject_tryout_result, add

@receiver(post_save, sender=TryoutSubmission, 
dispatch_uid='create_student_subject_tryout_result')
def result_calculation(sender, instance, raw, created, **kwargs):
    if created:
       print('Calculating result')
       create_student_subject_tryout_result.delay(
        instance.student.id,
        instance.tryout.id
       )
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.