What could cause a Django webpage rendering on main domain but not subdomain and localhost?
I’m trying to solve an issue with djangoproject.com. The footer on the bottom right has a “Corporate Membership”
link under “Support Us”
. The “Corporate Membership”
link works when the url is https://www.djangoproject.com/foundation/corporate-membership/%E2%80%9D
but not in case of https://docs.djangoproject.com/foundation/corporate-membership/%E2%80%9D
or https://dashboard.djangoproject.com/foundation/corporate-membership/%E2%80%9D
. It also raises a Page not Found (404)
error on the development server, like so
I searched the repo and couldn't find any template for this link, if the template doesn't exist how is it rendering in production?
urls/www.py
from django.conf import settings
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.contrib.contenttypes import views as contenttypes_views
from django.contrib.flatpages.sitemaps import FlatPageSitemap
from django.contrib.sitemaps import views as sitemap_views
from django.urls import include, path, re_path
from django.views.decorators.cache import cache_page
from django.views.generic import RedirectView, TemplateView
from django.views.static import serve
from accounts import views as account_views
from aggregator.feeds import CommunityAggregatorFeed, CommunityAggregatorFirehoseFeed
from blog.feeds import WeblogEntryFeed
from blog.sitemaps import WeblogSitemap
from foundation.feeds import FoundationMinutesFeed
from foundation.views import CoreDevelopers
admin.autodiscover()
sitemaps = {
"weblog": WeblogSitemap,
"flatpages": FlatPageSitemap,
}
urlpatterns = [
path("", TemplateView.as_view(template_name="homepage.html"), name="homepage"),
path(
"start/overview/",
TemplateView.as_view(template_name="overview.html"),
name="overview",
),
path("start/", TemplateView.as_view(template_name="start.html"), name="start"),
# to work around a permanent redirect stored in the db that existed
# before the redesign:
path("overview/", RedirectView.as_view(url="/start/overview/", permanent=False)),
path("accounts/", include("accounts.urls")),
# Admin password reset
path(
"admin/password_reset/",
auth_views.PasswordResetView.as_view(),
name="admin_password_reset",
),
path(
"admin/password_reset/done/",
auth_views.PasswordResetDoneView.as_view(),
name="password_reset_done",
),
path(
"reset/<uidb64>/<token>/",
auth_views.PasswordResetConfirmView.as_view(),
name="password_reset_confirm",
),
path(
"reset/done/",
auth_views.PasswordResetCompleteView.as_view(),
name="password_reset_complete",
),
path("admin/", admin.site.urls),
path("community/", include("aggregator.urls")),
path(
"conduct/",
TemplateView.as_view(template_name="conduct/index.html"),
name="code_of_conduct",
),
path(
"conduct/faq/",
TemplateView.as_view(template_name="conduct/faq.html"),
name="conduct_faq",
),
path(
"conduct/reporting/",
TemplateView.as_view(template_name="conduct/reporting.html"),
name="conduct_reporting",
),
path(
"conduct/enforcement-manual/",
TemplateView.as_view(template_name="conduct/enforcement.html"),
name="conduct_enforcement",
),
path(
"conduct/changes/",
TemplateView.as_view(template_name="conduct/changes.html"),
name="conduct_changes",
),
path(
"diversity/",
TemplateView.as_view(template_name="diversity/index.html"),
name="diversity",
),
path(
"diversity/changes/",
TemplateView.as_view(template_name="diversity/changes.html"),
name="diversity_changes",
),
path("contact/", include("contact.urls")),
path("foundation/django_core/", CoreDevelopers.as_view()),
path("foundation/minutes/", include("foundation.urls.meetings")),
path("foundation/", include("members.urls")),
path("fundraising/", include("fundraising.urls")),
# Used by docs search suggestions
re_path(
r"^r/(?P<content_type_id>\d+)/(?P<object_id>.*)/$",
contenttypes_views.shortcut,
name="contenttypes-shortcut",
),
# User stats
path("~<username>/", account_views.user_profile, name="user_profile"),
# Feeds
path("rss/weblog/", WeblogEntryFeed(), name="weblog-feed"),
path("rss/community/", RedirectView.as_view(url="/rss/community/blogs/")),
path(
"rss/community/firehose/",
CommunityAggregatorFirehoseFeed(),
name="aggregator-firehose-feed",
),
path("rss/community/<slug>/", CommunityAggregatorFeed(), name="aggregator-feed"),
path(
"rss/foundation/minutes/",
FoundationMinutesFeed(),
name="foundation-minutes-feed",
),
# django-push
path("subscriber/", include("django_push.subscriber.urls")),
# Trac schtuff
path("trac/", include("tracdb.urls")),
# Styleguide
path(
"styleguide/",
TemplateView.as_view(template_name="styleguide.html"),
name="styleguide",
),
path(
"sitemap.xml",
cache_page(60 * 60 * 6)(sitemap_views.sitemap),
{"sitemaps": sitemaps},
),
path("weblog/", include("blog.urls")),
path("download/", include("releases.urls")),
path("svntogit/", include("svntogit.urls")),
path("", include("legacy.urls")),
]
if settings.DEBUG:
urlpatterns += [
path("m/<path:path>", serve, {"document_root": settings.MEDIA_ROOT}),
]
try:
import debug_toolbar
except ImportError:
pass
else:
urlpatterns += [
path("__debug__/", include(debug_toolbar.urls)),
]
members/urls.py
from django.urls import path
from django.views.generic import RedirectView, TemplateView
from members.views import (
CorporateMemberBadgesView,
CorporateMemberRenewView,
CorporateMemberSignUpView,
IndividualMemberListView,
TeamsListView,
corporate_member_list_view,
)
app_name = "members"
urlpatterns = [
path(
"developer-members/",
RedirectView.as_view(pattern_name="members:individual-members"),
name="developer-members",
),
path(
"individual-members/",
IndividualMemberListView.as_view(),
name="individual-members",
),
path("corporate-members/", corporate_member_list_view, name="corporate-members"),
path(
"corporate-membership/join/",
CorporateMemberSignUpView.as_view(),
name="corporate-members-join",
),
path(
"corporate-membership/renew/<token>/",
CorporateMemberRenewView.as_view(),
name="corporate-members-renew",
),
path(
"corporate-membership/join/thanks/",
TemplateView.as_view(
template_name="members/corporate_members_join_thanks.html"
),
name="corporate-members-join-thanks",
),
path(
"corporate-members/badges/",
CorporateMemberBadgesView.as_view(),
name="corporate-members-badges",
),
path("teams/", TeamsListView.as_view(), name="teams"),
]
settings/common.py
# Settings for www.djangoproject.com
import json
import os
from pathlib import Path
# Utilities
PROJECT_PACKAGE = Path(__file__).resolve().parent.parent
# The full path to the repository root.
BASE_DIR = PROJECT_PACKAGE.parent
data_dir_key = "DJANGOPROJECT_DATA_DIR"
DATA_DIR = (
Path(os.environ[data_dir_key]) if data_dir_key in os.environ else BASE_DIR.parent
)
try:
with DATA_DIR.joinpath("conf", "secrets.json").open() as handle:
SECRETS = json.load(handle)
except OSError:
SECRETS = {
"secret_key": "a",
"superfeedr_creds": ["any@email.com", "some_string"],
}
# Django settings
CACHE_MIDDLEWARE_SECONDS = 60 * 5 # 5 minutes
CACHE_MIDDLEWARE_KEY_PREFIX = "django"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv("DJANGO_DB_NAME", "djangoproject"),
"USER": SECRETS.get("db_user", "djangoproject"),
"HOST": SECRETS.get("db_host", ""),
"PASSWORD": SECRETS.get("db_password", ""),
"PORT": SECRETS.get("db_port", ""),
},
"trac": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv("TRAC_DB_NAME", "code.djangoproject"),
"USER": SECRETS.get("trac_db_user", "code.djangoproject"),
"HOST": SECRETS.get("trac_db_host", ""),
"PASSWORD": SECRETS.get("trac_db_password", ""),
"PORT": SECRETS.get("trac_db_port", ""),
},
}
DATABASE_ROUTERS = ["tracdb.db_router.TracRouter"]
DEFAULT_FROM_EMAIL = "noreply@djangoproject.com"
FUNDRAISING_DEFAULT_FROM_EMAIL = "fundraising@djangoproject.com"
FIXTURE_DIRS = [str(PROJECT_PACKAGE.joinpath("fixtures"))]
INSTALLED_APPS = [
"accounts",
"aggregator",
"blog",
"contact",
"dashboard",
"docs",
"foundation",
"legacy",
"members",
"releases",
"svntogit",
"tracdb",
"fundraising",
"django_recaptcha",
"registration",
"django_hosts",
"sorl.thumbnail",
"djmoney",
"django.contrib.sites",
"django.contrib.auth",
"django.contrib.admin",
"django.contrib.contenttypes",
"django.contrib.flatpages",
"django.contrib.humanize",
"django.contrib.messages",
"django.contrib.postgres",
"django.contrib.redirects",
"django.contrib.sessions",
"django.contrib.staticfiles",
"django.contrib.sitemaps",
"django_push.subscriber",
"django_read_only",
# Temporary fix for Sphinx bug.https://github.com/sphinx-doc/sphinx/issues/13448
# Can be removed (and code deleted) once fixed.
"_sphinx_13448_workaround",
]
LANGUAGE_CODE = "en-us"
LOGGING = {
"version": 1,
"disable_existing_loggers": True,
"formatters": {
"simple": {"format": "[%(name)s] %(levelname)s: %(message)s"},
"full": {"format": "%(asctime)s [%(name)s] %(levelname)s: %(message)s"},
"django.server": {
"()": "django.utils.log.ServerFormatter",
"format": "[%(server_time)s] %(message)s",
},
},
"filters": {
"require_debug_false": {
"()": "django.utils.log.RequireDebugFalse",
},
},
"handlers": {
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "simple",
},
"django.server": {
"level": "INFO",
"class": "logging.StreamHandler",
"formatter": "django.server",
},
},
"loggers": {
"django.request": {
"handlers": [],
"level": "ERROR",
"propagate": False,
},
"django.server": {
"handlers": ["django.server"],
"level": "INFO",
"propagate": False,
},
},
}
LOGIN_REDIRECT_URL = "edit_profile"
MEDIA_URL = "/m/"
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"django_hosts.middleware.HostsRequestMiddleware",
# Put LocaleMiddleware before SessionMiddleware to prevent
# the former from accessing the session and adding
# 'Vary: Cookie' to all responses.
"djangoproject.middleware.ExcludeHostsLocaleMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.middleware.common.CommonMiddleware",
"django.contrib.flatpages.middleware.FlatpageFallbackMiddleware",
"django.contrib.redirects.middleware.RedirectFallbackMiddleware",
"django_hosts.middleware.HostsResponseMiddleware",
]
ROOT_URLCONF = "djangoproject.urls.www"
SECRET_KEY = str(SECRETS["secret_key"])
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTOCOL", "https")
SERVER_EMAIL = "root@djangoproject.com"
SESSION_COOKIE_HTTPONLY = True
SILENCED_SYSTEM_CHECKS = [
"security.W008", # SSL redirect is handled by nginx
"security.W009", # SECRET_KEY is setup through Ansible secrets
]
SITE_ID = 1
STATICFILES_DIRS = [str(PROJECT_PACKAGE.joinpath("static"))]
STATIC_URL = "/s/"
STATICFILES_FINDERS = (
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
)
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [str(PROJECT_PACKAGE.joinpath("templates"))],
"APP_DIRS": True,
"OPTIONS": {
"builtins": [
"django_hosts.templatetags.hosts_override",
],
"context_processors": [
"django.contrib.auth.context_processors.auth",
"django.template.context_processors.debug",
"django.template.context_processors.i18n",
"django.template.context_processors.static",
"django.template.context_processors.media",
"django.contrib.messages.context_processors.messages",
"docs.context_processors.docs_version",
"releases.context_processors.django_version",
"aggregator.context_processors.community_stats",
"django.template.context_processors.request",
],
},
},
]
TIME_ZONE = "America/Chicago"
USE_I18N = True
USE_TZ = False
# django-contact-form / Akismet settings
AKISMET_API_KEY = "c892e4962244"
# django-hosts settings
DEFAULT_HOST = "www"
HOST_SCHEME = "http"
HOST_SITE_TIMEOUT = 3600
ROOT_HOSTCONF = "djangoproject.hosts"
# django-registration settings
ACCOUNT_ACTIVATION_DAYS = 3
REGISTRATION_EMAIL_HTML = False
# aggregator / PubSubHubbub settings
FEED_APPROVERS_GROUP_NAME = "feed-approver"
# django-push settings
PUSH_HUB = "https://push.superfeedr.com/"
PUSH_CREDENTIALS = "aggregator.utils.push_credentials"
# django-money settings
CURRENCIES = ("USD",)
# SUPERFEEDR_CREDS is a 2 element list in the form of [email,secretkey]
SUPERFEEDR_CREDS = SECRETS.get("superfeedr_creds")
# Fastly credentials
FASTLY_API_KEY = SECRETS.get("fastly_api_key")
FASTLY_SERVICE_URL = SECRETS.get("fastly_service_url")
# Stripe settings
# only testing keys as fallback values here please!
STRIPE_SECRET_KEY = SECRETS.get("stripe_secret_key", "sk_test_x6zP4wd7Z5jcvDOJbbHZlHHt")
STRIPE_PUBLISHABLE_KEY = SECRETS.get(
"stripe_publishable_key", "pk_test_TyB5jcROwK8mlCNrn3dCwW7l"
)
STRIPE_ENDPOINT_SECRET = SECRETS.get("stripe_endpoint_secret", "insecure")
# product IDs
PRODUCTS = {
"monthly": {
"product_id": SECRETS.get("stripe_product_id_monthly", "dummy_monthly_id"),
"interval": "month",
"interval_count": 1,
},
"quarterly": {
"product_id": SECRETS.get("stripe_product_id_quarterly", "dummy_quarterly_id"),
"interval": "month",
"interval_count": 3,
},
"yearly": {
"product_id": SECRETS.get("stripe_product_id_yearly", "dummy_yearly_id"),
"interval": "year",
"interval_count": 1,
},
"onetime": {
"product_id": SECRETS.get("stripe_product_id_onetime", "dummy_onetime_id"),
"recurring": False,
},
}
# sorl-thumbnail settings
THUMBNAIL_PRESERVE_FORMAT = True
THUMBNAIL_ALTERNATIVE_RESOLUTIONS = [2]
# dashboard settings
TRAC_URL = "https://code.djangoproject.com/"
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
FORMS_URLFIELD_ASSUME_HTTPS = True
settings/dev.py
from .common import * # noqa
ALLOWED_HOSTS = [
"www.djangoproject.localhost",
"djangoproject.localhost",
"docs.djangoproject.localhost",
"dashboard.djangoproject.localhost",
] + SECRETS.get("allowed_hosts", [])
LOCALE_MIDDLEWARE_EXCLUDED_HOSTS = ["docs.djangoproject.localhost"]
DEBUG = True
THUMBNAIL_DEBUG = DEBUG
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.dummy.DummyCache",
"LOCATION": "trololololol",
},
"docs-pages": {
"BACKEND": "django.core.cache.backends.dummy.DummyCache",
"LOCATION": "docs-pages",
},
}
CSRF_COOKIE_SECURE = False
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
MEDIA_ROOT = str(DATA_DIR.joinpath("media_root"))
SESSION_COOKIE_SECURE = False
STATIC_ROOT = str(DATA_DIR.joinpath("static_root"))
# Docs settings
DOCS_BUILD_ROOT = DATA_DIR.joinpath("djangodocs")
# django-hosts settings
PARENT_HOST = "djangoproject.localhost:8000"
# django-push settings
PUSH_SSL_CALLBACK = False
# Enable optional components
if DEBUG:
try:
import debug_toolbar # NOQA
except ImportError:
pass
else:
INSTALLED_APPS.append("debug_toolbar")
INTERNAL_IPS = ["127.0.0.1"]
MIDDLEWARE.insert(
MIDDLEWARE.index("django.middleware.common.CommonMiddleware") + 1,
"debug_toolbar.middleware.DebugToolbarMiddleware",
)
MIDDLEWARE.insert(
MIDDLEWARE.index("debug_toolbar.middleware.DebugToolbarMiddleware") + 1,
"djangoproject.middleware.CORSMiddleware",
)
SILENCED_SYSTEM_CHECKS = SILENCED_SYSTEM_CHECKS + [
# Default test keys for development.
"django_recaptcha.recaptcha_test_key_error"
]
setting/prod.py
from .common import * # noqa
DOMAIN_NAME = os.getenv("DOMAIN_NAME", "djangoproject.com")
if not os.getenv("DJANGO_DB_NAME"):
raise ValueError("You must set DJANGO_DB_NAME in deployed environments.")
ALLOWED_HOSTS = [
f"www.{DOMAIN_NAME}",
DOMAIN_NAME,
f"docs.{DOMAIN_NAME}",
f"dashboard.{DOMAIN_NAME}",
] + SECRETS.get("allowed_hosts", [])
LOCALE_MIDDLEWARE_EXCLUDED_HOSTS = [f"docs.{DOMAIN_NAME}"]
DEBUG = os.getenv("DJANGO_DEBUG", "false").lower() == "true"
THUMBNAIL_DEBUG = DEBUG
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": SECRETS.get("cache_default_url", "redis://localhost:6379"),
},
# We use a separate cache for docs so we can purge it when docs are rebuilt
"docs-pages": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": SECRETS.get("cache_docs_url", "redis://localhost:6379/2"),
},
}
CSRF_COOKIE_SECURE = True
LOGGING["handlers"]["syslog"] = {
"formatter": "full",
"level": "DEBUG",
"class": "logging.handlers.SysLogHandler",
"address": "/dev/log",
"facility": "local4",
}
LOGGING["loggers"]["django.request"]["handlers"].append("syslog")
MEDIA_ROOT = str(DATA_DIR.joinpath("media"))
MEDIA_URL = f"https://media.{DOMAIN_NAME}/"
MIDDLEWARE = (
["django.middleware.cache.UpdateCacheMiddleware"]
+ MIDDLEWARE
+ ["django.middleware.cache.FetchFromCacheMiddleware"]
)
SESSION_COOKIE_SECURE = True
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
},
}
STATIC_ROOT = str(DATA_DIR.joinpath("static"))
STATIC_URL = f"https://static.{DOMAIN_NAME}/"
# Docs settings
DOCS_BUILD_ROOT = DATA_DIR.joinpath("data", "docbuilds")
# django-hosts settings
HOST_SCHEME = "https"
PARENT_HOST = DOMAIN_NAME
# django-push settings
PUSH_SSL_CALLBACK = True
# Log errors to Sentry instead of email, if available.
if "sentry_dsn" in SECRETS and not DEBUG:
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.redis import RedisIntegration
sentry_sdk.init(
dsn=SECRETS["sentry_dsn"],
integrations=[
DjangoIntegration(transaction_style="function_name"),
RedisIntegration(),
],
traces_sample_rate=0.1,
profiles_sample_rate=1.0,
)
# RECAPTCHA KEYS
# Defaults will trigger 'django_recaptcha.recaptcha_test_key_error' system check
if "recaptcha_public_key" in SECRETS:
RECAPTCHA_PUBLIC_KEY = SECRETS.get("recaptcha_public_key")
RECAPTCHA_PRIVATE_KEY = SECRETS.get("recaptcha_private_key")
RECAPTCHA_REQUIRED_SCORE = 0.9
# Release artifacts are uploaded via the admin and are about 10Mb each
# The nginx configuration still restricts the upload size on most pages.
DATA_UPLOAD_MAX_MEMORY_SIZE = 50 * 1024 * 1024 # 50 Mb
footer.html
<div class="col-support-us">
<h3>Support Us</h3>
<ul>
<li><a href="{% url "fundraising:index" %}">Sponsor Django</a></li>
<li><a href="/foundation/corporate-membership/">Corporate membership</a></li>
<li><a href="https://django.threadless.com/" target="_blank">Official merchandise store</a></li>
<li><a href="/foundation/donate/#benevity-giving">Benevity Workplace Giving Program</a></li>
</ul>
</div>
</div>