Merge branch 'master' into pg-search
[mygpo.git] / mygpo / settings.py
blobde9d70bed2e71fff38bb7a02e78ed314e57ec72e
1 import re
2 import sys
3 import os.path
4 import dj_database_url
7 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
10 def get_bool(name, default):
11 return os.getenv(name, str(default)).lower() == 'true'
14 def get_intOrNone(name, default):
15 """ Parses the env variable, accepts ints and literal None"""
16 value = os.getenv(name, str(default))
17 if value.lower() == 'none':
18 return None
19 return int(value)
22 DEBUG = get_bool('DEBUG', False)
24 ADMINS = re.findall(r'\s*([^<]+) <([^>]+)>\s*', os.getenv('ADMINS', ''))
26 MANAGERS = ADMINS
28 DATABASES = {
29 'default': dj_database_url.config(
30 default='postgres://mygpo:mygpo@localhost/mygpo'),
34 _cache_used = bool(os.getenv('CACHE_BACKEND', False))
36 if _cache_used:
37 CACHES = {}
38 CACHES['default'] = {
39 'BACKEND': os.getenv(
40 'CACHE_BACKEND',
41 'django.core.cache.backends.memcached.MemcachedCache'),
42 'LOCATION': os.getenv('CACHE_LOCATION'),
46 # Local time zone for this installation. Choices can be found here:
47 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
48 # although not all choices may be available on all operating systems.
49 # If running in a Windows environment this must be set to the same as your
50 # system time zone.
51 TIME_ZONE = 'UTC'
53 # Language code for this installation. All choices can be found here:
54 # http://www.i18nguy.com/unicode/language-identifiers.html
55 LANGUAGE_CODE = 'en-us'
57 SITE_ID = 1
59 # If you set this to False, Django will make some optimizations so as not
60 # to load the internationalization machinery.
61 USE_I18N = True
63 STATIC_ROOT = 'staticfiles'
64 STATIC_URL = '/media/'
66 STATICFILES_DIRS = (
67 os.path.abspath(os.path.join(BASE_DIR, '..', 'htdocs', 'media')),
71 TEMPLATES = [{
72 'BACKEND': 'django.template.backends.django.DjangoTemplates',
73 'DIRS': [],
74 'OPTIONS': {
75 'debug': DEBUG,
76 'context_processors': [
77 'django.contrib.auth.context_processors.auth',
78 'django.template.context_processors.debug',
79 'django.template.context_processors.i18n',
80 'django.template.context_processors.media',
81 'django.template.context_processors.static',
82 'django.template.context_processors.tz',
83 'django.contrib.messages.context_processors.messages',
84 'mygpo.web.google.analytics',
85 'mygpo.web.google.adsense',
86 # make the debug variable available in templates
87 # https://docs.djangoproject.com/en/dev/ref/templates/api/#django-core-context-processors-debug
88 'django.template.context_processors.debug',
90 # required so that the request obj can be accessed from
91 # templates. this is used to direct users to previous
92 # page after login
93 'django.template.context_processors.request',
95 'libraries': {
96 'staticfiles' : 'django.templatetags.static',
98 'loaders': [
99 ('django.template.loaders.cached.Loader', [
100 'django.template.loaders.app_directories.Loader',
107 MIDDLEWARE = [
108 'django.middleware.common.CommonMiddleware',
109 'django.middleware.csrf.CsrfViewMiddleware',
110 'django.contrib.sessions.middleware.SessionMiddleware',
111 'django.contrib.auth.middleware.AuthenticationMiddleware',
112 'django.middleware.locale.LocaleMiddleware',
113 'django.contrib.messages.middleware.MessageMiddleware',
116 ROOT_URLCONF = 'mygpo.urls'
118 INSTALLED_APPS = [
119 'django.contrib.contenttypes',
120 'django.contrib.messages',
121 'django.contrib.admin',
122 'django.contrib.humanize',
123 'django.contrib.auth',
124 'django.contrib.sessions',
125 'django.contrib.staticfiles',
126 'django.contrib.sites',
127 'django.contrib.postgres',
128 'djcelery',
129 'mygpo.core',
130 'mygpo.podcasts',
131 'mygpo.chapters',
132 'mygpo.search',
133 'mygpo.users',
134 'mygpo.api',
135 'mygpo.web',
136 'mygpo.publisher',
137 'mygpo.subscriptions',
138 'mygpo.history',
139 'mygpo.favorites',
140 'mygpo.usersettings',
141 'mygpo.data',
142 'mygpo.userfeeds',
143 'mygpo.suggestions',
144 'mygpo.directory',
145 'mygpo.categories',
146 'mygpo.episodestates',
147 'mygpo.maintenance',
148 'mygpo.share',
149 'mygpo.administration',
150 'mygpo.pubsub',
151 'mygpo.podcastlists',
152 'mygpo.votes',
153 'django_nose',
156 try:
157 import debug_toolbar
158 INSTALLED_APPS += ['debug_toolbar']
159 MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
161 except ImportError:
162 pass
165 try:
166 import opbeat
168 if not DEBUG:
169 INSTALLED_APPS += ['opbeat.contrib.django']
171 # add opbeat middleware to the beginning of the middleware classes list
172 MIDDLEWARE = \
173 ['opbeat.contrib.django.middleware.OpbeatAPMMiddleware'] + \
174 MIDDLEWARE
176 except ImportError:
177 pass
180 ACCOUNT_ACTIVATION_DAYS = int(os.getenv('ACCOUNT_ACTIVATION_DAYS', 7))
182 AUTHENTICATION_BACKENDS = (
183 'mygpo.users.backend.CaseInsensitiveModelBackend',
184 'mygpo.web.auth.EmailAuthenticationBackend',
187 SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
189 # TODO: use (default) JSON serializer for security
190 # this would currently fail as we're (de)serializing datetime objects
191 # https://docs.djangoproject.com/en/1.5/topics/http/sessions/#session-serialization
192 SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
195 MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
197 USER_CLASS = 'mygpo.users.models.User'
199 LOGIN_URL = '/login/'
201 CSRF_FAILURE_VIEW = 'mygpo.web.views.csrf_failure'
204 DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', '')
206 SECRET_KEY = os.getenv('SECRET_KEY', '')
208 if 'test' in sys.argv:
209 SECRET_KEY = 'test'
211 GOOGLE_ANALYTICS_PROPERTY_ID = os.getenv('GOOGLE_ANALYTICS_PROPERTY_ID', '')
213 DIRECTORY_EXCLUDED_TAGS = os.getenv('DIRECTORY_EXCLUDED_TAGS', '').split()
215 FLICKR_API_KEY = os.getenv('FLICKR_API_KEY', '')
217 SOUNDCLOUD_CONSUMER_KEY = os.getenv('SOUNDCLOUD_CONSUMER_KEY', '')
219 MAINTENANCE = get_bool('MAINTENANCE', False)
222 ALLOWED_HOSTS = ['*']
225 LOGGING = {
226 'version': 1,
227 'disable_existing_loggers': False,
228 'formatters': {
229 'verbose': {
230 'format': '%(asctime)s %(name)s %(levelname)s %(message)s',
233 'filters': {
234 'require_debug_false': {
235 '()': 'django.utils.log.RequireDebugFalse'
238 'handlers': {
239 'console': {
240 'level': os.getenv('LOGGING_CONSOLE_LEVEL', 'DEBUG'),
241 'class': 'logging.StreamHandler',
242 'formatter': 'verbose',
244 'mail_admins': {
245 'level': 'ERROR',
246 'filters': ['require_debug_false'],
247 'class': 'django.utils.log.AdminEmailHandler',
250 'loggers': {
251 'django': {
252 'handlers': os.getenv('LOGGING_DJANGO_HANDLERS',
253 'console').split(),
254 'propagate': True,
255 'level': os.getenv('LOGGING_DJANGO_LEVEL', 'WARN'),
257 'mygpo': {
258 'handlers': os.getenv('LOGGING_MYGPO_HANDLERS', 'console').split(),
259 'level': os.getenv('LOGGING_MYGPO_LEVEL', 'INFO'),
261 'celery': {
262 'handlers': os.getenv('LOGGING_CELERY_HANDLERS',
263 'console').split(),
264 'level': os.getenv('LOGGING_CELERY_LEVEL', 'DEBUG'),
269 _use_log_file = bool(os.getenv('LOGGING_FILENAME', False))
271 if _use_log_file:
272 LOGGING['handlers']['file'] = {
273 'level': 'INFO',
274 'class': 'logging.handlers.RotatingFileHandler',
275 'filename': os.getenv('LOGGING_FILENAME'),
276 'maxBytes': 10000000,
277 'backupCount': 10,
278 'formatter': 'verbose',
282 # minimum number of subscribers a podcast must have to be assigned a slug
283 PODCAST_SLUG_SUBSCRIBER_LIMIT = int(os.getenv(
284 'PODCAST_SLUG_SUBSCRIBER_LIMIT', 10))
286 # minimum number of subscribers that a podcast needs to "push" one of its
287 # categories to the top
288 MIN_SUBSCRIBERS_CATEGORY = int(os.getenv('MIN_SUBSCRIBERS_CATEGORY', 10))
290 # maximum number of episode actions that the API processes immediatelly before
291 # returning the response. Larger requests will be handled in background.
292 # Handler can be set to None to disable
293 API_ACTIONS_MAX_NONBG = int(os.getenv('API_ACTIONS_MAX_NONBG', 100))
294 API_ACTIONS_BG_HANDLER = 'mygpo.api.tasks.episode_actions_celery_handler'
297 ADSENSE_CLIENT = os.getenv('ADSENSE_CLIENT', '')
299 ADSENSE_SLOT_BOTTOM = os.getenv('ADSENSE_SLOT_BOTTOM', '')
301 # we're running behind a proxy that sets the X-Forwarded-Proto header correctly
302 # see https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
303 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
306 # enabled access to staff-only areas with ?staff=<STAFF_TOKEN>
307 STAFF_TOKEN = os.getenv('STAFF_TOKEN', None)
309 # Flattr settings -- available after you register your app
310 FLATTR_KEY = os.getenv('FLATTR_KEY', '')
311 FLATTR_SECRET = os.getenv('FLATTR_SECRET', '')
313 # Flattr thing of the webservice. Will be flattr'd when a user sets
314 # the "Auto-Flattr gpodder.net" option
315 FLATTR_MYGPO_THING = os.getenv(
316 'FLATTR_MYGPO_THING',
317 'https://flattr.com/submit/auto?user_id=stefankoegl&url=http://gpodder.net'
320 # The User-Agent string used for outgoing HTTP requests
321 USER_AGENT = 'gpodder.net (+https://github.com/gpodder/mygpo)'
323 # Base URL of the website that is used if the actually used parameters is not
324 # available. Request handlers, for example, can access the requested domain.
325 # Code that runs in background can not do this, and therefore requires a
326 # default value. This should be set to something like 'http://example.com'
327 DEFAULT_BASE_URL = os.getenv('DEFAULT_BASE_URL', '')
330 ### Celery
332 BROKER_URL = os.getenv('BROKER_URL', 'redis://localhost')
333 CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
335 SERVER_EMAIL = os.getenv('SERVER_EMAIL', 'no-reply@example.com')
337 CELERY_TASK_RESULT_EXPIRES = 60 * 60 # 1h expiry time in seconds
339 CELERY_ACCEPT_CONTENT = ['pickle', 'json']
341 CELERY_SEND_TASK_ERROR_EMAILS = get_bool('CELERY_SEND_TASK_ERROR_EMAILS',
342 False)
344 BROKER_POOL_LIMIT = get_intOrNone('BROKER_POOL_LIMIT', 10)
346 ### Google API
348 GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID', '')
349 GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET', '')
351 # URL where users of the site can get support
352 SUPPORT_URL = os.getenv('SUPPORT_URL', '')
355 FEEDSERVICE_URL = os.getenv('FEEDSERVICE_URL', 'http://feeds.gpodder.net/')
358 # time for how long an activation is valid; after that, an unactivated user
359 # will be deleted
360 ACTIVATION_VALID_DAYS = int(os.getenv('ACTIVATION_VALID_DAYS', 10))
363 OPBEAT = {
364 "ORGANIZATION_ID": os.getenv('OPBEAT_ORGANIZATION_ID', ''),
365 "APP_ID": os.getenv('OPBEAT_APP_ID', ''),
366 "SECRET_TOKEN": os.getenv('OPBEAT_SECRET_TOKEN', ''),
369 LOCALE_PATHS = [
370 os.path.abspath(os.path.join(BASE_DIR, 'locale')),
373 INTERNAL_IPS = os.getenv('INTERNAL_IPS', '').split()
375 EMAIL_BACKEND = os.getenv('EMAIL_BACKEND',
376 'django.core.mail.backends.smtp.EmailBackend')
378 PODCAST_AD_ID = os.getenv('PODCAST_AD_ID')
380 TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
382 NOSE_ARGS = [
383 '--with-doctest',
384 '--stop',
385 '--where=mygpo',