Django-nonrel with Google App Engine: Missing AutoloadMiddelware class? - django

I just deployed a website using Google App Engine that I built using Django. However, whenever I try to view my site live, I get a 500 error, and when I go into the App Engine dashboard and check the logs, I see the error:
"ImproperlyConfigured: Middleware module "autoload.middleware" does
not define a "AutoloadMiddelware" class"
But this doesn't quite make sense as I checked the autoload folder in my project and inside, there is a middeware.py file that indeed defines an AutoloadMiddleware class as follows:
from django.utils.importlib import import_module
from django.conf import settings
# load all models.py to ensure signal handling installation or index loading
# of some apps
for app in settings.INSTALLED_APPS:
try:
import_module('%s.models' % (app))
except ImportError:
pass
class AutoloadMiddleware(object):
"""Empty because the import above already does everything for us"""
pass
Is there something wrong with the import, perhaps? Is it possible my deployment didn't upload the necessary django modules in addition to those in my project folder?

Make sure you add it to your settings.py
MIDDLEWARE_CLASSES = (
# This loads the index definitions, so it has to come first
'autoload.middleware.AutoloadMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
)

Related

Cross-project iframe testing on localhost with different ports

I am relatively new to iFrame, and what I try to do is to load project A in an iframe that is in project B. Project A is running as a Django project on localhost:8000, and project B as a separate Django project on localhost:8001. Inside the project B, I have a Django template with the following content:
<iframe src="http://127.0.0.1:8000" height="500px" width="500px"></iframe>
The problem is that instead of seeing the content of project A home page, I see error message stating that:
127.0.0.1 refused to connect
Is there anything I am terribly missing?
This is the default Clickjacking Protection [Django docs] by Django kicking into action (Great for us!), but this is preventing you from loading the iframe in your other project. There are various options to solve this issue:
If you want all your pages from your project to be put inside an iframe then you can remove 'django.middleware.clickjacking.XFrameOptionsMiddleware' from your MIDDLEWARE settings:
MIDDLEWARE = [
...
'django.middleware.clickjacking.XFrameOptionsMiddleware',
...
]
If this is for only specific views you can use the xframe_options_exempt decorator:
from django.views.decorators.clickjacking import xframe_options_exempt
#xframe_options_exempt
def some_view(request):
...

Django Debug Toolbar show queries from middleware

I am using Django Debug Toolbar to debug and optimize my website. I am also using some custom middleware to do things such as checking to see if a user is logged in and is allowed to access the url they are trying to view, querying ads, etc.
In this middleware, sometimes SQL queries are performed, but the queries don't show up under the 'queries' panel in DDT. Is there any way to get DDT to recognize and track middleware?
According to the documentation:
The order of MIDDLEWARE_CLASSES is important. You should include the
Debug Toolbar middleware as early as possible in the list. However, it
must come after any other middleware that encodes the response’s
content, such as GZipMiddleware.
The solution is to put debug_toolbar.middleware.DebugToolbarMiddleware before your custom middleware in MIDDLEWARE_CLASSES.
One of the place i found error is when I added a separate file debugtoolbar.py for all settings pertaining to enable debug_toolbar. I just imported this in my settings_local.py but it was calling somehow twice and it was not showing the queries.
As soon as I added a conditional statement to add
import os
import sys
from my_project.settings import INSTALLED_APPS, MIDDLEWARE_CLASSES
DEBUG_TOOLBAR_APPS_NAME = 'debug_toolbar'
if DEBUG_TOOLBAR_APPS_NAME not in INSTALLED_APPS:
INSTALLED_APPS += ( DEBUG_TOOLBAR_APPS_NAME, )
DEBUG_TOOLBAR_MIDDLEWARE = 'debug_toolbar.middleware.DebugToolbarMiddleware'
if DEBUG_TOOLBAR_MIDDLEWARE not in MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = ( DEBUG_TOOLBAR_MIDDLEWARE, ) + MIDDLEWARE_CLASSES
def custom_show_toolbar(request):
return True
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': 'my_project.settings.custom_show_toolbar',
}
It started working all fine. Hope this will save someone's time.

You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware

I am new to Django.
I am trying to run an app and I need to add a new user to admin. The server is running. When I enter the info fir the new user and hit "save" I get the error below. I am using django-trunk.
MessageFailure at /admin/auth/user/add/
You cannot add messages without installing
django.contrib.messages.middleware.MessageMiddleware
Request Method: POST
Request URL: http://localhost:8000/admin/auth/user/add/
Django Version: 1.6.dev20130403090717
Exception Type: MessageFailure
Exception Value: You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware
Any ideas of what might be happening?
For me the problem was specific to unit testing. It turns out that some middleware won't work in some kinds of unit tests, more info here:
https://code.djangoproject.com/ticket/17971
and here:
Why don't my Django unittests know that MessageMiddleware is installed?
My solution was to just mock out the messages framework for those tests, there may be better solutions (the django test client?)
Check if you have django.contrib.messages in INSTALLED_APPS and django.contrib.messages.middleware.MessageMiddleware in MIDDLEWARE_CLASSES.
If you are running normal django code, you should add
django.contrib.messages.middleware.MessageMiddleware to your middlewares as others have suggested
If you are running a test case and using request factory then as #hwjp answered above, it's a bug (that won't be fixed). The request factory doesn't call the middlewares and developers don't intend to change this behaviour.
There is however a simple solution.
in your test settings file (i.e settings/test.py) add the following line
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
in your test code you can write code like this
request = RequestFactory().get("/")
# Add support django messaging framework
request._messages = messages.storage.default_storage(request)
and that's it. Passing this request object to any code that uses django messages will work without a problem.
Check if it is
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
instead of
MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
Tuple name should be MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES depreciated https://docs.djangoproject.com/en/2.1/releases/1.10/#id3
2018 update
In django 2.0+ name in settings was changed.
Right now use MIDDLEWARE instead of MIDDLEWARE_CLASSES name of list in settings!
If the request is needed in tests, it can be mocked as suggested by #Ramast.
I found the solution mentioned in the bug ticket (closed, won't fix) to be helpful.
from django.contrib.messages.storage.fallback import FallbackStorage
from django.test import RequestFactory
def dummy_request():
"""Dummy request for testing purposes with message support."""
request = RequestFactory().get('/')
# Add support django messaging framework
setattr(request, 'session', 'session')
setattr(request, '_messages', FallbackStorage(request))
return request
Probably you put a wrong WSGI_request when usually called request as a parameter to add_message() method
I met the same error.
You have to notice the order of middleware in MIDDLEWARE_CLASSES.
Insert the corresponding middleware in the final.Like this,
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
Note the order arrangement.
If your issue is simulating these middlewares during unit testing, you can spoof this by writing a couple of little helpers:
def add_session_to_request(request: HttpRequest) -> HttpRequest:
"""Adds session support to a RequestFactory generated request."""
middleware = SessionMiddleware(get_response=lambda request: None)
middleware.process_request(request)
request.session.save()
return request
def add_messages_to_request(request: HttpRequest) -> HttpRequest:
"""Adds message/alert support to a RequestFactory generated request."""
request._messages = FallbackStorage(request)
return request
You can then call these in your test function at the point your request needs to have the middleware bound and just pass in the request you're using, which should keep your tests happy. :)
# To suppress the errors raised when triggering .messages through APIRequestFactory(),
# we need to bind both a session and messages storage on the fly
add_session_to_request(replacement_request)
add_messages_to_request(replacement_request)

Unable to login to django admin view with valid username and password

I know this question has been asked several times before but most of the question were asked long ago and old answers did not work for me.
I have a django-nonrel based app which is using dbindexer as backend and deployed on GAE. I am able to view homepage of my app which does not require login.
But when I try to login to admin view, it gives "wrong username / password"
On my local development server, if I use "manage.py runserver", then I am able to login on admin page. But If I run my app through GAE launcher, then I am not able to login.
I could gather that GAE launcher uses different django from "manage.py runserver".
So, how can I make GAE (on launcher as well as on deployment server) use django-nonrel?
Other details:
app.yaml does NOT include "django" library.
settings.py
DATABASES['native'] = DATABASES['default']
DATABASES['default'] = {'ENGINE': 'dbindexer', 'TARGET': 'native'}
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djangotoolbox',
'autoload',
'dbindexer',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
'django.contrib.admindocs',
'djangoappengine',
'testapp',
)
urls.py
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
)
UPDATE 1::
As #dragonx pointed out, I need to run
python manage.py remote createsuperuser and create the user.
On local server, when I run 'manage.py syncdb', it fills database with initializing data which also includes creating a superuser. I use 'initial_data.yaml' inside 'fixtures' directory for this and is read automatically by syncdb command.
So, Is there any way to run "syncdb' on server side? Somehow I assumed this is happening automatically at deployment just like 'manage.py runserver' happens itself and I do not need to run app manually.
If I run manage.py remote syncdb, it blurts out following error:
google.appengine.api.datastore_errors.NeedIndexError: no matching index found.
<<ed>>some stack trace<<ed>>
The suggested index for this query is:
- kind: django_content_type
properties:
- name: app_label
- name: name
Update 2:
Instead of using appcfg.py update site command, if you use python manage.py deploy from your app directory, it runs fixtures on remote server. Don't know what's doing what.
manage.py remote loaddata initdata.yaml can also be used to initialize remote database.
But even after this, I still do not see the fixtures data loaded in admin interface i.e. it seems database was not initialized or maybe admin view is badly broken. But I'd save that for another question~
When you run python manage.py runserver it starts a local dev server on your local machine. It has it's own dev datastore on your local machine. At some point you created an admin user in your local database.
When you deploy on app engine, it runs your code on Google's servers. There's a datastore there, but it doesn't share the data on your dev server. You'll need to create an admin user in the production datastore too. Try:
python manage.py remote createsuperuser

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!