Django--URL Caching Failing for Class Based Views - django

I've built a RESTful API on top of the Django Rest Framework. The URL conf for the API is composed of class based views.
I would like to cache these views, however, the following is failing. Any thoughts on why that might be and how I could change it?
from django.views.decorators.cache import cache_page
urlpatterns = patterns('',
url(r'^dounces/?$', cache_page(60*60)(DounceListView.as_view(resource=DounceResource)), name='dounces_api'),
I have the following middleware installed.
'django.middleware.gzip.GZipMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.transaction.TransactionMiddleware',
'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
AND for local testing, i'm using the default caching backend:
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',

change your urlconf to
urlpatterns = patterns('',
url(r'^dounces/?$', cache_page(60*60)(DounceListView.as_view(resource=DounceResource)), name='dounces_api'),
)
also see https://docs.djangoproject.com/en/1.7/topics/cache/#specifying-per-view-cache-in-the-urlconf

The other answer is out of date. The correct way is detailed here:
https://docs.djangoproject.com/en/1.6/topics/cache/#specifying-per-view-cache-in-the-urlconf
It has to now be done this way:
urlpatterns = patterns('',
url(r'^dounces/?$', cache_page(60*60)(DounceListView.as_view(resource=DounceResource)), name='dounces_api'),
)

I dont see any "django.middleware.cache.UpdateCacheMiddleware" and "django.middleware.cache.FetchFromCacheMiddleware". I dont think it can cache properly without it.
https://docs.djangoproject.com/en/2.2/topics/cache/

Related

Django csrf token not refreshed after first login

I have hosted a website at http://cognezic-dev.ap-south-1.elasticbeanstalk.com/login/. On closer inspection, the form has the same csrf token across page refreshes and browsers, which I suspect to be the cause of the issue,this works fine on the local django server.Dont know where this is being cached. I have added CSRF Middleware in the settings.py too.
You can use the test credentials as username bismeet and password bis12345 for testing.
I have also tried creating a custom middleware as follows:
from django.middleware.csrf import rotate_token, CsrfViewMiddleware
from django.utils.deprecation import MiddlewareMixin
class CSRFRefresh(CsrfViewMiddleware,MiddlewareMixin):
def process_response(self, request, response):
print("Custom MiddleWare called")
rotate_token(request)
return response
But it still fails.
My settings.py with custom middleware contains:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'solvesto.middleware.csrf_refresh.CSRFRefresh'
]
If not using the custom middleware,I use:
'django.middleware.csrf.CsrfViewMiddleware'
instead of
'solvesto.middleware.csrf_refresh.CSRFRefresh'
The only last resort I see to make this work is to remove csrf altogether,which is of course,bad for security.
I removed the csrf security,no other solution,works now.

Django-hosts wrong URLS.py

I am trying to configure something like this
user2.example.com -> load urls_user.py
www.example.com -> load urls.py
The issue I am facing now is everything is loaded through urls_user.py
I am using django-hosts from https://django-hosts.readthedocs.io/en/latest/
settings.py
MIDDLEWARE_CLASSES = (
'django_hosts.middleware.HostsRequestMiddleware' ,
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'user_shop.subdomainMiddleware.subdomainMiddleware',
'django_hosts.middleware.HostsResponseMiddleware'
)
ROOT_URLCONF = 'e_com.urls'
ROOT_HOSTCONF = 'e_com.hosts'
DEFAULT_HOST = "www"
hosts.py
from django.conf import settings
from django_hosts import patterns, host
host_patterns = patterns('',
host(r'www', settings.ROOT_URLCONF, name='www'),
host(r'127', settings.ROOT_URLCONF, name='127'),
host(r'(?!www)\w+', 'e_com.urls_user', name='wildcard'),
)
Even if i remove everything to do with urls_user, it will still load that file.
I am working on localhost and use hexxie:8000 to run my subdomains.
------EDIT------
I have the django_hosts in my installed apps, thing is it worked for once until I turned off my server and restart it, from then the problem persists till now.
'user_shop.subdomainMiddleware.subdomainMiddleware' is just a script to get the subdomain
class subdomainMiddleware:
def process_request(self,request):
domain_parts = request.get_host().split('.')
subdomain = "www"
if(len(domain_parts) > 2):
subdomain = domain_parts[0].lower()
request.subdomain = subdomain
And if I do a pip freeze this will show
altgraph==0.10.2
bdist-mpkg==0.5.0
bonjour-py==0.3
Django==1.8.3
django-hosts==1.4
django-subdomains==2.0.4
macholib==1.5.1
matplotlib==1.3.1
modulegraph==0.10.4
mysql==0.0.1
MySQL-python==1.2.5
numpy==1.8.0rc1
Pillow==2.9.0
py2app==0.7.3
pyasn1==0.1.8
pycrypto==2.6.1
pyobjc-core==2.5.1
pyobjc-framework-Accounts==2.5.1
pyobjc-framework-AddressBook==2.5.1
pyobjc-framework-AppleScriptKit==2.5.1
pyobjc-framework-AppleScriptObjC==2.5.1
pyobjc-framework-Automator==2.5.1
pyobjc-framework-CFNetwork==2.5.1
pyobjc-framework-Cocoa==2.5.1
pyobjc-framework-Collaboration==2.5.1
pyobjc-framework-CoreData==2.5.1
pyobjc-framework-CoreLocation==2.5.1
pyobjc-framework-CoreText==2.5.1
pyobjc-framework-DictionaryServices==2.5.1
pyobjc-framework-EventKit==2.5.1
pyobjc-framework-ExceptionHandling==2.5.1
pyobjc-framework-FSEvents==2.5.1
pyobjc-framework-InputMethodKit==2.5.1
pyobjc-framework-InstallerPlugins==2.5.1
pyobjc-framework-InstantMessage==2.5.1
pyobjc-framework-LatentSemanticMapping==2.5.1
pyobjc-framework-LaunchServices==2.5.1
pyobjc-framework-Message==2.5.1
pyobjc-framework-OpenDirectory==2.5.1
pyobjc-framework-PreferencePanes==2.5.1
pyobjc-framework-PubSub==2.5.1
pyobjc-framework-QTKit==2.5.1
pyobjc-framework-Quartz==2.5.1
pyobjc-framework-ScreenSaver==2.5.1
pyobjc-framework-ScriptingBridge==2.5.1
pyobjc-framework-SearchKit==2.5.1
pyobjc-framework-ServiceManagement==2.5.1
pyobjc-framework-Social==2.5.1
pyobjc-framework-SyncServices==2.5.1
pyobjc-framework-SystemConfiguration==2.5.1
pyobjc-framework-WebKit==2.5.1
pyOpenSSL==0.13.1
pyparsing==2.0.1
python-dateutil==1.5
pytz==2013.7
scipy==0.13.0b1
six==1.4.1
Twisted==13.2.0
xattr==0.6.4
zope.interface==4.1.1
I have found the error. It is an error in my urls.py file.

Django Debug Toolbar shows at root URL, but not in app URL

I have a new project and I'm trying to set up Django Debug Toolbar. First I tried the quick setup, which only involves adding 'debug_toolbar' to my list of installed apps. With this, the debug toolbar showed up when I went to my root URL, but it did not work for my app urls/views. I should not that presently, my root URL is not linked to a view, so it was showing a django error page.
Since the quick start didn't work, I went with the explicit setup. I updated my settings file:
DEBUG_TOOLBAR_PATCH_SETTINGS = False
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
And updated my project-level urls.py:
if settings.DEBUG: # make sure the toolbar is above ?CKeditor and FeinCMS
import debug_toolbar
urlpatterns += patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
)
But now it doesn't show up anywhere.
In my app view, I've added a {% debug %} to the template. The template debug output does seem to indicate that the debug toolbar middleware has been loaded:
'debug_toolbar': <module 'debug_toolbar' from '/home/joseph/.virtualenvs/myproject/local/lib/python2.7/site-packages/debug_toolbar/__init__.pyc'>,
'debug_toolbar.collections': None,
'debug_toolbar.compat': <module 'debug_toolbar.compat' from '/home/joseph/.virtualenvs/myproject/local/lib/python2.7/site-packages/debug_toolbar/compat.pyc'>,
'debug_toolbar.django': None,
'debug_toolbar.importlib': None,
'debug_toolbar.middleware': <module 'debug_toolbar.middleware' from '/home/joseph/.virtualenvs/myproject/local/lib/python2.7/site-packages/debug_toolbar/middleware.pyc'>,
I'm not sure why this isn't working. My django version is 1.8 and my debug toolbar version is 1.3.2.
My solution to this problem was to add <body></body> tags to the template.
I got it from the "Tips" section on django-debug-toolbar site.
The Debug Toolbar will only display when DEBUG = True in your project’s settings. It will also only display if the mimetype of the response is either text/html or application/xhtml+xml and contains a closing </body> tag.
Source: django-debug-toolbar.readthedocs.io/en/stable/tips.html
If the toolbar works on index page (or any other) but not on another, missing body tags are probably the reason.

django-debug-toolbar won't display from production server

I'd like to view the Django Debug Toolbar when accessing my production website which is running Django 1.6. My server is running Debian 7.8, Nginx 1.2.1, and Gunicorn 19.1.1. However, when I try to access the site after adding DDT to my installed apps, I get the following error:
NoReverseMatch at /
u'djdt' is not a registered namespace
Exception Location: /home/mysite/venv/mysite/local/lib/python2.7/site-packages/django/core/urlresolvers.py in reverse, line 505
Error during template rendering
In template /home/mysite/venv/mysite/local/lib/python2.7/site-packages/debug_toolbar/templates/debug_toolbar/base.html, error at line 12
data-store-id="{{ toolbar.store_id }}" data-render-panel-url="{% url 'djdt:render_panel' %}"
I know it's not recommended that you run the toolbar in production but I just want to run it while I do some testing on my production server prior to opening it up for public use. As you might expect, it works just fine in my development environment on my laptop. I did some research and have ensured that I'm using the "explicit" setup as recommended here. I also ran the command "django-admin.py collectstatic" to ensure the toolbar's static files were collected into my STATIC_ROOT.
Since I'm running behind a proxy server, I also added some middleware to ensure that the client's IP address is being passed to the toolbar's middleware instead of my proxy's IP address. That didn't fix the problem either.
I'm showing all the settings which seem pertinent to this problem below. Is there something else I'm missing?
Thanks!
These are the pertinent base settings:
SETTINGS_ROOT = os.path.abspath(os.path.dirname(__file__).decode('utf-8'))
STATIC_ROOT = '/var/www/mysite/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(SETTINGS_ROOT, "../../static"),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.common.BrokenLinkEmailsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
TEMPLATE_DIRS = (
os.path.join(SETTINGS_ROOT, "../../templates"),
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Django management commands in 'scripts'
'scripts',
'apps.account',
)
These production-only settings get added to base settings in production:
DEBUG = True # DDT needs this to be True
TEMPLATE_DEBUG = DEBUG
INSTALLED_APPS += (
'django_extensions',
# I'm using Django 1.6
'debug_toolbar',
)
if 'debug_toolbar' in INSTALLED_APPS:
MIDDLEWARE_CLASSES += ('conf.middleware.DjangoDebugToolbarFix',
'debug_toolbar.middleware.DebugToolbarMiddleware', )
# I had to add this next setting after upgrading my OS to Mavericks
DEBUG_TOOLBAR_PATCH_SETTINGS = False
# IP for laptop and external IP needed by DDT
INTERNAL_IPS = ('76.123.67.152', )
DEBUG_TOOLBAR_CONFIG = {
'DISABLE_PANELS': [
'debug_toolbar.panels.redirects.RedirectsPanel',
],
'SHOW_TEMPLATE_CONTEXT': True,
'INTERCEPT_REDIRECTS': False
}
This is in my urls.py:
if 'debug_toolbar' in dev.INSTALLED_APPS:
import debug_toolbar
urlpatterns += patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
)
Here is the additional middleware:
class DjangoDebugToolbarFix(object):
"""Sets 'REMOTE_ADDR' based on 'HTTP_X_FORWARDED_FOR', if the latter is
set."""
def process_request(self, request):
if 'HTTP_X_FORWARDED_FOR' in request.META:
ip = request.META['HTTP_X_FORWARDED_FOR'].split(",")[0].strip()
request.META['REMOTE_ADDR'] = ip
I am using the exact same setup as OP describes, with the noticeable exception of running everything in a separate Docker container which make the IP of each service hard to predict.
This is how you force Django Debug Toolbar to always show (only use this locally, never in production):
def custom_show_toolbar(request):
return True # Always show toolbar, for example purposes only.
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': custom_show_toolbar,
}
Actually, you shouldn't set DEBUG to True on your production server, keep it False and check my solution below:
The default DDT callback (debug_toolbar.middleware.show_toolbar) checks are that DEBUG must be set to True, the IP of the request must be in INTERNAL_IPS, and the request must not be an AJAX request.
We can provide our own callback which excludes the DEBUG setting condition:
settings:
INTERNAL_IPS = ['YOUR.IP.ADDRESS.HERE'] # put your client IP address here (not server IP!)
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': lambda request: not request.is_ajax() and request.META.get('REMOTE_ADDR', None) in INTERNAL_IPS
}
You can check HTTP_X_FORWARDED_FOR if you wish too, it is up to you.
urls:
if 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]
If you are on docker the following code helped me get the internal ip.
# Debug Toolbar
if DEBUG:
import os
import socket
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
INTERNAL_IPS = [ip[:-1] + '1' for ip in ips] + ['127.0.0.1', '10.0.2.2', ]
credit goes here https://gist.github.com/douglasmiranda/9de51aaba14543851ca3#file-option2-py
And this answer has additional options: https://stackoverflow.com/a/49818040/317346
So django-debug-toolbar uses JavaScript to run as well. have you confirmed you have n conflicting JS scripts affecting your setup? I had a hell of a time with one project using DjDT and it was a back-to-top script that was interfering...
Also, I know you have lots of extra code to handle your proxy situation, but have you uan it straight out of the box to see if that works on your server? I might create a new virtualenv, start from scratch and make sure it works on your server and then proceed to add apps and additional configuration.
These are probably thing you have thought of but I thought I'd add them anyway since your question hasn't received much action.
Good luck.
I had to add the following to the project url.py file to fix the issue. After that debug tool bar is displayed.
from django.conf.urls import include
from django.conf.urls import patterns
from django.conf import settings
if settings.DEBUG:
import debug_toolbar
urlpatterns += patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
)

Concatenate Django Settings "MIDDLEWARE_CLASSES"

I want to import the django default settings, using from django.conf import global_settings, and then add MIDDLEWARE_CLASSES to it. I like to do this with my settings so that I know what I have added and what is default. So my settings file would look like this:
from django.conf import global_settings
...
global_settings.MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
This strategy works for other settings, such as TEMPLATE_CONTEXT_PROCESSORS, but when I try it, it isn't working. I added print global_settings.MIDDLEWARE_CLASSES after adding the Debug Toolbar Middlware and this was my output when using runserver
('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware')
('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware')
Validating models...
0 errors found
Django version 1.3.1, using settings 'canada.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
If you scroll over you can see that it runs through the settings twice. The second time it adds the setting again. How can I prevent this? To I have to just hard code my MIDDLEWARE_CLASSES in the settings? Also is there a good reason not to import the default django settings?
I don't think it's recommended that you make changes directly to global_settings variable. The Django core does a lot of screwing around with it as it merges in all the stuff you define in settings.py, so it may be that your changes are getting overwritten.
If you really want to derive your variables from global_settings directly, I'd make a local copy, then modify that. Example:
GLOBAL_MIDDLEWARE_CLASSES = global_settings.MIDDLEWARE_CLASSES
LOCAL_MIDDLEWARE_CLASSES = ('debug_toolbar.middleware.DebugToolbarMiddleware',)
MIDDLEWARE_CLASSES = GLOBAL_MIDDLEWARE_CLASSES + LOCAL_MIDDLEWARE_CLASSES
Django should then pick up that you've defined a new version of MIDDLEWARE_CLASSES, and insert it into global_middleware using the proper process.
This being said, I personally would prefer to have all the middleware classes there for me to see and re-arrange if needed. By using the method you've chosen, you don't know what could change between Django revisions!