Django-hosts wrong URLS.py - django

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.

Related

Using PUBLIC_SCHEMA_URLCONF in django-tenant-schemas

I am trying to have django-tenant-schemas re-route users if they visit the base domain using the optional setting PUBLIC_SCHEMA_URLCONF. Whenever I visit the
base url I get this response:
I'm hoping someone can tell me what the value of PUBLIC_SCHEMA_URLCONF should be based on my project structure or if anything else might be wrong. I want to use the urls from public_website when people try to access the base domain.
My project directory looks like this:
website
├──approvals
├──batches
├──customauth
├──email_portal
├──exports
├──file_downloads
├──password_reset
├──payroll
├──payroll_codes
├──reports
├──scheduling
├──shifts
├──static
├──templates
├──website
| ├──migrations
| ├──static
| ├──templates
| └──settings
| ├──__init__.py
| ├──base.py
| ├──prod.py
| └──dev.py
├──scheduling
├──public_website
| ├──__init__.py
| └──urls.py
└──manage.py
And I want PUBLIC_SCHEMA_URLCONF to refer to the urls in public_website, which look like:
from django.conf.urls import include, url
import website.views as website_views
from django.contrib import admin
from django.http import HttpResponse
url_patterns = [
url(r'^$', lambda request: HttpResponse('ok')),
url(r'^admin/login/', website_views.Login.as_view()),
url(r'^admin/', include(admin.site.urls)) # user authentication urls
]
Here are the relevant bits in my settings:
DJANGO_APPS = (
'jet',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'django.contrib.admin',
'django_user_agents',
'django_ses',
# 'admin_reorder'
)
MY_APPS_WITH_MODELS = (
'customauth',
'payroll_codes',
'scheduling',
'payroll',
'shifts',
'email_portal',
'tutor_training_tracker'
)
MY_APPS_WITHOUT_MODELS = (
'exports',
'reports',
'file_downloads',
'batches',
'approvals'
)
SHARED_APPS = (
'tenant_schemas',
'website',
'public_website'
)
TENANT_APPS = DJANGO_APPS + MY_APPS_WITH_MODELS
INSTALLED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + DJANGO_APPS + MY_APPS_WITHOUT_MODELS + MY_APPS_WITH_MODELS))
ROOT_URLCONF = 'website.urls'
PUBLIC_SCHEMA_URLCONF = 'public_website.urls'
TENANT_MODEL = "website.Client"
DEFAULT_FILE_STORAGE = "tenant_schemas.storage.TenantFileSystemStorage"
Any help would be greatly appreciated.
Solution:
(Thanks to Thomas for writing the middleware for me)
Add custom middleware class:
from django.conf import settings
from django.db import connection
from tenant_schemas.middleware import MIDDLEWARE_MIXIN
from tenant_schemas.utils import remove_www, get_tenant_model, get_public_schema_name
class CustomTenantMiddleware(MIDDLEWARE_MIXIN):
def get_tenant(self, model, hostname, request):
return model.objects.get(domain_url=hostname)
def hostname_from_request(self, request):
""" Extracts hostname from request. Used for custom requests filtering.
By default removes the request's port and common prefixes.
"""
return remove_www(request.get_host().split(':')[0]).lower()
def process_request(self, request):
# Connection needs first to be at the public schema, as this is where
# the tenant metadata is stored.
connection.set_schema_to_public()
hostname = self.hostname_from_request(request)
TenantModel = get_tenant_model()
try:
# get_tenant must be implemented by extending this class.
tenant = self.get_tenant(TenantModel, hostname, request)
assert isinstance(tenant, TenantModel)
request.tenant = tenant
connection.set_tenant(request.tenant)
except (TenantModel.DoesNotExist, AssertionError):
request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
request.public_tenant = True
return
if hasattr(settings, 'PUBLIC_SCHEMA_URLCONF') and request.tenant.schema_name == get_public_schema_name():
request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
and reference it in settings:
MIDDLEWARE_CLASSES = (
# 'tenant_schemas.middleware.TenantMiddleware',
'website.middleware.CustomTenantMiddleware',
'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',
'django_user_agents.middleware.UserAgentMiddleware',
'admin_reorder.middleware.ModelAdminReorder',
'website.middleware.CustomTenantMiddleware',
# 'djadmin.middleware.DJMiddleware',
)
I maintain Django-Tenants which is a fork of django-tenant-schemas. The public url file gets called when the domain doesn't match a tenant. However depending on the middleware you have this can result in this not working. If this is the case write custom middleware for the tenant. You may also want edit you host file as it hard to test with out editing. What middleware are you using?
Make sure you have installed latest version of django-tenants and these settings are set in settings.py:
SHOW_PUBLIC_IF_NO_TENANT_FOUND = True # I wonder why this setting is not meintioned in docs.
PUBLIC_SCHEMA_URLCONF = 'project_name.urls_public'

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!

Django--URL Caching Failing for Class Based Views

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/