Skip to content
Advertisement

How to track download link in django?

I followed these method to track how much downloaded the file was. But total_downloads always remains same (it’s 0). How to increment total_downloads field by 1 after every download?

My models.py:

from django.db import models

class FilesAdmin(models.Model):
    id_no = models.IntegerField()
    name = models.CharField(max_length=20)
    loc = models.CharField(max_length=20)
    adminupload = models.FileField(upload_to='media')
    total_downloads = models.IntegerField(default=0)

    def __str__(self):
        return self.name

views.py. In this program, I want to increment the number of downloads. But it’s 0 in admin site.

from django.shortcuts import render
from django.http import HttpResponse
import os
from .models import FilesAdmin

def index(request):
    context = {'file': FilesAdmin.objects.all()}
    return render(request,'libooki/index.html',context)


def download(request,path,pk):
    file_path = os.path.join(settings.MEDIA_ROOT,path)
    if os.path.exists(file_path):
        with open(file_path,'rb') as fh:
            response = HttpResponse(fh.read(),content_type="application/adminupload")
            response['Content-Disposition']='inline;filename'+os.path.basename(file_path)
            n = FilesAdmin.objects.get(pk=pk)
            n.total_downloads += 1
            n.save()
            return response

urls.py

from django.contrib import admin
from django.urls import include,path
from django.conf import settings
from django.conf.urls.static import static
from libooki import views #here's libooki is my app name
from django.conf.urls import url
from django.views.static import serve

urlpatterns = [
    path('', views.index,name='index'),
    path('admin/', admin.site.urls),
    url(r'^download/(?P<path>.*)$',serve,{'document_root': settings.MEDIA_ROOT}),
]
if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

index.html from where people can download the file

<!DOCTYPE html>
<html lang="en">
<head>
      <meta charset="UTF-8">
      <title>hello</title>
</head>
<body>
    {% for post in file%}
        <h2>{{post.name}}</h2>
        <a href="{{post.adminupload.url}}" download="{{post.adminupload.url}}">Download</a>

    {% endfor %}


</body>
</html>

Advertisement

Answer

Try using Axios to download the file,

In the template, Try this-

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>hello</title>
</head>

<body>
    {% for post in file %}
    <h2>{{post.name}}</h2>
    <button onclick="downloadFile('{{ post.adminupload.url }}', '{{ post.id }}')">Download file</button>
    {% endfor %}
</body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
    function downloadFile(file_url, id) {
        axios({
            method: "GET",
            url: file_url,
            responseType: 'blob',
            onDownloadProgress: event => {
                if (event.loaded === event.total) {
                    // send a GET request to the backend telling that download is complete
                    axios({
                            method: "GET",
                            url: "/post-downloaded/" + id, // send id of the post, user is downloading
                        })
                        .then(console.log("download incremented"))
                        .catch(error => console.log(error))
                }
            }
        }).then(response => {
            // download the file
            const aTag = document.createElement("a");
            aTag.href = URL.createObjectURL(resp.data);
            aTag.download = "filename." + resp.data.type.split("/")[1];
            aTag.click();
        })
    }
</script>

</html>

Now in the backend, create a route for /post-downloaded/

In your urls.py file-

from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
from libooki import views
from django.views.static import serve

urlpatterns = [
    path('', views.index,name='index'),
    path('post-downloaded/<int:pk>', views.post_downloaded), # add this route
    path('admin/', admin.site.urls),
]
if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

And in the views.py file create this-

from django.shortcuts import render
from django.http import HttpResponse
from .models import FilesAdmin

def index(request):
    context = {'file': FilesAdmin.objects.all()}
    return render(request,'libooki/index.html',context)

def post_downloaded(request, pk):
    file = FilesAdmin.objects.get(pk=pk)
    file.total_downloads += 1
    file.save()
    return HttpResponse("download added")

This should get the work done

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement