Counting page views for a User uploaded PDF in Django

286 Views Asked by At

I have a webapp where a user can upload a pdf. I want to be able to see how many times the PDF is viewed by other user, all of which would be anonymous users. At the moment I didn't have to write a view to view the PDF, in the 'view PDF' button i Just link the uploaded PDF's URL, which directs to the PDF document.

Button to view PDF

<a href="{{ doc.File.url }}" class="btn btn-outline-secondary" style="margin: 2px;">View PDF</a>

The issue arises, in that when a user uploads a PDF doc, i create a qr code which contains the URL of that doc. So i only want to count the views that are from the qr scan in, and not redirected from the button. How can i do this seeing as i don't actually have a view to render the PDF?

One way i was thinking of is writing a return redirect view, with an incrementer for the views instance in the model? or to use the Django F() statement to pull in the views instance and then increment it.

Any ideas?

2

There are 2 best solutions below

0
On

For the QR code, you could encode the URL as URL + "&qr=true". That way it will show up in your HTTP logs with a different URL.

0
On

You have to make an Ajax call to your views.py on button click and update the model instance view_count field.

Example models.py

# I am taking a sample model
class Document(models.Model):
    File = models.FileField(upload_to='uploads/')
    count = models.IntegerField(default=0)

views.py

from django.http import HttpResponse
def index(request,id):
    doc = Document.objects.get(pk=id) #whatever file you are serving
    if request.is_ajax():
        if request.method == 'POST':
           #if you don't want to increment when file author opens then you can write the condition here 
           doc.count = doc.count+1 #incrementing your file view count
           doc.save()
           return HttpResponse({'msg': 'success'}, content_type="application/json")
    return render(request,'index.html',{'doc':doc}) 

Instead of using anchor I will use button to avoid redirecting before ajax response.

index.html

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    
<button id="view_pdf" href="{{ doc.File.url }}" class="btn btn-outline-secondary" style="margin: 2px;">View PDF</button>

<script>
$("#view_pdf").on('click', function(){
     $.ajax({
            type: 'POST',
            url: '',
            dataType: 'json',
            cache: false,
            async: true,
            data: {
               csrfmiddlewaretoken: "{{csrf_token}}",
            },
            success: function(json){
              window.location.href = "{{ doc.File.url }}" // you can redirect to your pdf here
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
                alert(errorThrown);
            }
     });
});

</script>