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:
- Install django-background-tasks library
pip install django-background-tasks
- Adding decorator in your function
from background_task import background @background def create_post_view
- Calling function
from django.utils import timezone create_post_view(....,schedule=timezone.now()) # at a specific time
The desired function will be executed asynchronosly.