Madiyor
Madiyor

Reputation: 811

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

Upvotes: 0

Views: 2244

Answers (1)

Sagar Adhikari
Sagar Adhikari

Reputation: 1392

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.

Upvotes: 2

Related Questions