Skip to content
Advertisement

How to execute tasks in parallel in Django (Asynchronous programming)?

I am developing a simple view_count. I just want to count the views if the requesting user has not seen the object for a day with its existing user account or ip address. I am using Django and djangorestframework.

Here is some sample code for retrieve action.

def get_ip_address(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip


def create_post_view(post, user, request):
    print("before sleeping")
    PostView.objects.create(post=post,
                            user=user,
                            ip_address=get_ip_address(request)
                            )
    post.view_count += 1
    post.save(update_fields=("view_count", ))
    print(post)

class PostModelViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [IsAdminOrReadOnly, ]
    pagination_class = DefaultLimitOffsetPagination

    def retrieve(self, request, *args, **kwargs):
        obj = self.get_object()
        user = request.user if request.user.id else None
        vwd = PostView.objects.filter(post=obj.id,
                                      user=user,
                                      ip_address=get_ip_address(request),
                                      viewed_on__startswith=date.today())
        if not vwd:
            create_post_view(obj, user, request)
        obj.view_count += 1
        return Response(PostDetailSerializer(obj).data,
                        status=status.HTTP_200_OK)

It is pretty simple. I get the requesting object from database and check if the object is viewed by the the user or the same ip address in a day. If the post object is not viewed I simple need to create PostView instance which means that next view is not going to be counted on viewed day.

My question: How can I run it in a way that I will return the Response object and at the same time fire the function and not wait it to complete?

Thanks in advance

Advertisement

Answer

You can use celery. But, given the simplicity of your problem, I think it’s easier to use django-background-tasks. https://django-background-tasks.readthedocs.io/en/latest/.

It’s as easy as this:

  1. Install django-background-tasks library
pip install django-background-tasks
  1. Adding decorator in your function
from background_task import background

@background
def create_post_view
  1. Calling function
from django.utils import timezone

create_post_view(....,schedule=timezone.now()) # at a specific time

The desired function will be executed asynchronosly.

Advertisement