0

I am beginner with django.
On my website I would like to create a library which allows downloads of executable files which I created myself. I would like to count how many times each file has been downloaded.

I thought to use a middleware, knowing that I am able to make a middleware which counts and displays the number of times a page has been viewed :

def stats_middleware (get_response):
    def middleware (request):
        try :
            p = Stat.objects.get(url = request.path)
            p.views_number = F('views_number')+1
            p.save
        except Stat.DoesNotExist :
            p = Stat.objects.create(url= request.path)

        response = get_response(request)

        response.content += bytes(
            "cette page a été vue {} fois.".format(p.views_number),
            "utf8"
        )
        return response
    return middleware

I thought that if I managed to open the download in a new page, I could count the number of times it appears and thus the number of downloads of the file, but I did not manage to open the download in another tab.

How can I do this?

ChrisM
  • 505
  • 6
  • 18
Robin Joseph
  • 107
  • 10
  • 1
    How are you serving your django website? Usually static files are [served using server like Apache or Nginx in production](https://docs.djangoproject.com/en/2.2/howto/static-files/), so django website never even gets the requests for static files. – matevzpoljanc Sep 02 '19 at 08:27
  • Modifiying the response content this way is a terrible idea anyway - a response's content is not necessarily plain text - it can be HTML (which will then be invalid), XML (which will then be invalid AND unusable - no parser will accept it), JSON (idem), any other defined text format (csv, yaml etc) which will also be rendered unusable, or any binary format which will then be totally broken. And even if your response happened to be a plain text doc, you'd still be breaking the HTTP "content-length" response header... – bruno desthuilliers Sep 02 '19 at 11:51

1 Answers1

1

You do not need to use middleware. Serving files through django is bad idea and is very ineffective. To control access to files and so on the servers creates special mechanism. X-Sendfile in Apache and X-Accel-Redirect in Ngnix. You need only create special response header in your View. In same View you can count downloads.

You car read more here: Django - Understanding X-Sendfile

And try to use this package: https://github.com/johnsensible/django-sendfile

Sample code:

from sendfile import sendfile

def download(request):
    # here increment counter of download 
    return sendfile(request, file_name)

Grzegorz Bokota
  • 1,736
  • 11
  • 19
  • Thank's for answer me ! I am really beginner with django and I don't absolutely understand the concept of servers. Can you show me an example of a simple view using x-sendfile. And how can I say if my host use Apache or Ngnix ? Thank you for your answer, and sorry for my english. – Robin Joseph Sep 03 '19 at 07:26
  • If you run developer version of Django then no webserwer is in usage (Django serve everything). When you deploy then you need to know on which server type you will use. For more information read Django docs https://docs.djangoproject.com/en/2.2/howto/deployment/ – Grzegorz Bokota Sep 03 '19 at 08:59