2

I'm trying to put all the GET requests that appear in console into the database from django. For example:

console log:

[23/May/2019 13:58:44] "GET /testapp/ HTTP/1.1" 200 409
[23/May/2019 13:58:45] "GET /testapp/page2/ HTTP/1.1" 200 172

I'm trying to get the timestamp, page URL and user name from it and put in the database, so the entries looks something like this in the database:

id  user    pageURL        timeStamp
96  naeem   /testapp/       2019-05-23 09:37:12.640613
97  naeem   /testapp/page2/ 2019-05-23 09:37:13.317271

This is the code I have written for the middleware:

from TestApp.models import ActivityLog


class AccessLogs(object):

    # One-time config
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)

        # Add the user and page info into DB
        try:
            ActivityLog(user=request.user, pageURL=request.path).save()
        except Exception as e:
            print(e)

        return response

The problem is that it gives me the desired result, but it does not get the results if I click on a downloadable file, or an image. Like I have a static image on the website which is downloaded on click, like:

<a href="{% static 'TestApp/media/cat.jpg' %}" download>Click here to open image</a>

So if I click on that, it shows in the console that the image was downloaded, but it doesn't put that in the database. Is there any way to make this work? Any help will be appreciated!

EDIT: settings.py:

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SECRET_KEY = ''

DEBUG = True

ALLOWED_HOSTS = []

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'TestApp',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'TestApp.middleware.LoggingMiddleware.AccessLogs',
]

ROOT_URLCONF = 'Test.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Test.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'
MEDIA_URL = '/media/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'media')
]

Models:

from django.db import models

class ActivityLog(models.Model):
    user = models.CharField(max_length=1024)
    pageURL = models.CharField(max_length=1024)
    timeStamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "activity_logs"

EDIT2: The file I'm trying to access is stored in TestWebsite/TestApp/static/TestApp/media/cat.jpg

TestWebsite/TestApp/url.py:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.homePage, name='homePage'),
    path('page2/', views.homePage2, name='homepage2')
]

TestWebsite/TestWebsite/urls.py

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from django.views.static import serve
from django.views.decorators.cache import never_cache

nocache_serve = never_cache(serve)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('testapp/', include('TestApp.url')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT, view=nocache_serve)

TestWebsite/TestApp/views.py:

from django.shortcuts import render, HttpResponse
import datetime

def homePage(request):
    time = datetime.datetime.now()
    return render(request, "TestApp/homePage.html", {"time": time})

def homePage2(request):
    return render(request, "TestApp/homePage2.html")
Naeem Khan
  • 950
  • 4
  • 13
  • 34

1 Answers1

3

In general Django's Middleware are created for effective request/response management. It has own phases (process_request(), process_view(), process_response()) and so on. Every time request reaches on server, Middleware is called (But This does not happen every time, when serving static files). This is because of caching behaviour. Django caches static/media files in browser cache (using Cache-Control header). When resource is cached, on next request resource is read from browser cache and request does not reach on the server. Django uses from django.views.static import serve method for serving static/media files. (This method sets correct HTTP headers for caching).

In your urls.py add these lines. This is the most important here.

from django.conf import settings
from django.conf.urls.static import static
from django.views.static import serve
from django.views.decorators.cache import never_cache

nocache_serve = never_cache(serve) # never_cache is view decorator. we can use here, also. This will set correct HTTP headers to avoid caching behaviour.
urlpatterns = [
    #
    # your path goes here
    #
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT, view=nocache_serve)

settings.py

# I think you already have this configuration in settings.
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'media')
]

Now, You can log all incoming request (But do not forget, to avoid caching behaviour of static/media files is bad idea).

Do not forget to clear browser cache and restart server after adding this code.

Hope it helps.

gachdavit
  • 1,223
  • 1
  • 6
  • 7
  • Hi. I tried your solution but it did not seem to work. I did everything as you explained. – Naeem Khan May 23 '19 at 22:56
  • What you mean exactly ? Did you clear whole browser cache ? and restart server ? What problems do you have ? – gachdavit May 23 '19 at 22:57
  • I did clear the whole browser cache, restarted the server. But it is still not showing the static file in the database. – Naeem Khan May 23 '19 at 23:01
  • You mean media files (Your uploaded photos or static files including .js and .css) ? – gachdavit May 23 '19 at 23:02
  • I meant the media files which are in media folder are not showing up in the database. I tried testing the __call__ method if it is working when the user opens a media file, but it is still not firing up for media files. – Naeem Khan May 23 '19 at 23:06
  • Also, make monitoring using browser. Show me .js, .css, and media files are cached or not ? – gachdavit May 23 '19 at 23:06
  • Check with browser, are media files cached or not ? – gachdavit May 23 '19 at 23:06
  • The media file did get cached. I do not have any .js or .css files in static folders. – Naeem Khan May 23 '19 at 23:09
  • If they are cached, you did something wrong. Update your question and provide us your projects urls.py and settings.py file. – gachdavit May 23 '19 at 23:10
  • I have updated the post. Thank you so much for the help so far. – Naeem Khan May 23 '19 at 23:13
  • 1
    It works so good for me. I checked it again. Try other browser just for testing and clear whole data in browser including cookies, cache, forms, etc. – gachdavit May 23 '19 at 23:18
  • I tried it with a different browser but still I have the same result. The media file access is not getting logged in the database. Can you please try with the model and middleware that I have and check if it is logging the access to that file in database? – Naeem Khan May 23 '19 at 23:31
  • If request reaches server middleware will be called, then sql insert will be performed. All works for me. Strange what's wrong on your dev server. – gachdavit May 23 '19 at 23:46
  • This is not DB/Model problem, because request does not reach server at all. – gachdavit May 23 '19 at 23:47
  • The weird thing is, that it is not working for me on two different PCs running Chrome and Firefox. I will try working on it tomorrow with a fresh mind, but if it still doesn't work then I give up. Thank you for all the help! – Naeem Khan May 23 '19 at 23:53