Use psycopg2cffi for PyPy compatibility
[mygpo.git] / mygpo / settings.py
blobce799883be51bd8f07ba71a8661960cc1b6de09b
1 import re
2 import sys
3 import os.path
4 import dj_database_url
7 try:
8 from psycopg2cffi import compat
9 compat.register()
10 except ImportError:
11 pass
14 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
17 def get_bool(name, default):
18 return os.getenv(name, str(default)).lower() == 'true'
21 def get_intOrNone(name, default):
22 """ Parses the env variable, accepts ints and literal None"""
23 value = os.getenv(name, str(default))
24 if value.lower() == 'none':
25 return None
26 return int(value)
29 DEBUG = get_bool('DEBUG', False)
31 ADMINS = re.findall(r'\s*([^<]+) <([^>]+)>\s*', os.getenv('ADMINS', ''))
33 MANAGERS = ADMINS
35 DATABASES = {
36 'default': dj_database_url.config(
37 default='postgres://mygpo:mygpo@localhost/mygpo'),
41 _cache_used = bool(os.getenv('CACHE_BACKEND', False))
43 if _cache_used:
44 CACHES = {}
45 CACHES['default'] = {
46 'BACKEND': os.getenv(
47 'CACHE_BACKEND',
48 'django.core.cache.backends.memcached.MemcachedCache'),
49 'LOCATION': os.getenv('CACHE_LOCATION'),
53 # Local time zone for this installation. Choices can be found here:
54 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
55 # although not all choices may be available on all operating systems.
56 # If running in a Windows environment this must be set to the same as your
57 # system time zone.
58 TIME_ZONE = 'UTC'
60 # Language code for this installation. All choices can be found here:
61 # http://www.i18nguy.com/unicode/language-identifiers.html
62 LANGUAGE_CODE = 'en-us'
64 SITE_ID = 1
66 # If you set this to False, Django will make some optimizations so as not
67 # to load the internationalization machinery.
68 USE_I18N = True
70 STATIC_ROOT = 'staticfiles'
71 STATIC_URL = '/media/'
73 STATICFILES_DIRS = (
74 os.path.abspath(os.path.join(BASE_DIR, '..', 'htdocs', 'media')),
78 TEMPLATES = [{
79 'BACKEND': 'django.template.backends.django.DjangoTemplates',
80 'DIRS': [],
81 'OPTIONS': {
82 'debug': DEBUG,
83 'context_processors': [
84 'django.contrib.auth.context_processors.auth',
85 'django.template.context_processors.debug',
86 'django.template.context_processors.i18n',
87 'django.template.context_processors.media',
88 'django.template.context_processors.static',
89 'django.template.context_processors.tz',
90 'django.contrib.messages.context_processors.messages',
91 'mygpo.web.google.analytics',
92 'mygpo.web.google.adsense',
93 # make the debug variable available in templates
94 # https://docs.djangoproject.com/en/dev/ref/templates/api/#django-core-context-processors-debug
95 'django.template.context_processors.debug',
97 # required so that the request obj can be accessed from
98 # templates. this is used to direct users to previous
99 # page after login
100 'django.template.context_processors.request',
102 'libraries': {
103 'staticfiles' : 'django.templatetags.static',
105 'loaders': [
106 ('django.template.loaders.cached.Loader', [
107 'django.template.loaders.app_directories.Loader',
114 MIDDLEWARE = [
115 'django.middleware.common.CommonMiddleware',
116 'django.middleware.csrf.CsrfViewMiddleware',
117 'django.contrib.sessions.middleware.SessionMiddleware',
118 'django.contrib.auth.middleware.AuthenticationMiddleware',
119 'django.middleware.locale.LocaleMiddleware',
120 'django.contrib.messages.middleware.MessageMiddleware',
123 ROOT_URLCONF = 'mygpo.urls'
125 INSTALLED_APPS = [
126 'django.contrib.contenttypes',
127 'django.contrib.messages',
128 'django.contrib.admin',
129 'django.contrib.humanize',
130 'django.contrib.auth',
131 'django.contrib.sessions',
132 'django.contrib.staticfiles',
133 'django.contrib.sites',
134 'djcelery',
135 'mygpo.core',
136 'mygpo.podcasts',
137 'mygpo.chapters',
138 'mygpo.search',
139 'mygpo.users',
140 'mygpo.api',
141 'mygpo.web',
142 'mygpo.publisher',
143 'mygpo.subscriptions',
144 'mygpo.history',
145 'mygpo.favorites',
146 'mygpo.usersettings',
147 'mygpo.data',
148 'mygpo.userfeeds',
149 'mygpo.suggestions',
150 'mygpo.directory',
151 'mygpo.categories',
152 'mygpo.episodestates',
153 'mygpo.maintenance',
154 'mygpo.share',
155 'mygpo.administration',
156 'mygpo.pubsub',
157 'mygpo.podcastlists',
158 'mygpo.votes',
159 'django_nose',
162 try:
163 if DEBUG:
164 import debug_toolbar
165 INSTALLED_APPS += ['debug_toolbar']
166 MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
168 except ImportError:
169 pass
172 try:
173 import opbeat
175 if not DEBUG:
176 INSTALLED_APPS += ['opbeat.contrib.django']
178 except ImportError:
179 pass
182 ACCOUNT_ACTIVATION_DAYS = int(os.getenv('ACCOUNT_ACTIVATION_DAYS', 7))
184 AUTHENTICATION_BACKENDS = (
185 'mygpo.users.backend.CaseInsensitiveModelBackend',
186 'mygpo.web.auth.EmailAuthenticationBackend',
189 SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
191 # TODO: use (default) JSON serializer for security
192 # this would currently fail as we're (de)serializing datetime objects
193 # https://docs.djangoproject.com/en/1.5/topics/http/sessions/#session-serialization
194 SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
197 MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
199 USER_CLASS = 'mygpo.users.models.User'
201 LOGIN_URL = '/login/'
203 CSRF_FAILURE_VIEW = 'mygpo.web.views.csrf_failure'
206 DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', '')
208 SECRET_KEY = os.getenv('SECRET_KEY', '')
210 if 'test' in sys.argv:
211 SECRET_KEY = 'test'
213 GOOGLE_ANALYTICS_PROPERTY_ID = os.getenv('GOOGLE_ANALYTICS_PROPERTY_ID', '')
215 DIRECTORY_EXCLUDED_TAGS = os.getenv('DIRECTORY_EXCLUDED_TAGS', '').split()
217 FLICKR_API_KEY = os.getenv('FLICKR_API_KEY', '')
219 SOUNDCLOUD_CONSUMER_KEY = os.getenv('SOUNDCLOUD_CONSUMER_KEY', '')
221 MAINTENANCE = get_bool('MAINTENANCE', False)
224 ALLOWED_HOSTS = ['*']
227 LOGGING = {
228 'version': 1,
229 'disable_existing_loggers': False,
230 'formatters': {
231 'verbose': {
232 'format': '%(asctime)s %(name)s %(levelname)s %(message)s',
235 'filters': {
236 'require_debug_false': {
237 '()': 'django.utils.log.RequireDebugFalse'
240 'handlers': {
241 'console': {
242 'level': os.getenv('LOGGING_CONSOLE_LEVEL', 'DEBUG'),
243 'class': 'logging.StreamHandler',
244 'formatter': 'verbose',
246 'mail_admins': {
247 'level': 'ERROR',
248 'filters': ['require_debug_false'],
249 'class': 'django.utils.log.AdminEmailHandler',
252 'loggers': {
253 'django': {
254 'handlers': os.getenv('LOGGING_DJANGO_HANDLERS',
255 'console').split(),
256 'propagate': True,
257 'level': os.getenv('LOGGING_DJANGO_LEVEL', 'WARN'),
259 'mygpo': {
260 'handlers': os.getenv('LOGGING_MYGPO_HANDLERS', 'console').split(),
261 'level': os.getenv('LOGGING_MYGPO_LEVEL', 'INFO'),
263 'celery': {
264 'handlers': os.getenv('LOGGING_CELERY_HANDLERS',
265 'console').split(),
266 'level': os.getenv('LOGGING_CELERY_LEVEL', 'DEBUG'),
271 _use_log_file = bool(os.getenv('LOGGING_FILENAME', False))
273 if _use_log_file:
274 LOGGING['handlers']['file'] = {
275 'level': 'INFO',
276 'class': 'logging.handlers.RotatingFileHandler',
277 'filename': os.getenv('LOGGING_FILENAME'),
278 'maxBytes': 10000000,
279 'backupCount': 10,
280 'formatter': 'verbose',
284 # minimum number of subscribers a podcast must have to be assigned a slug
285 PODCAST_SLUG_SUBSCRIBER_LIMIT = int(os.getenv(
286 'PODCAST_SLUG_SUBSCRIBER_LIMIT', 10))
288 # minimum number of subscribers that a podcast needs to "push" one of its
289 # categories to the top
290 MIN_SUBSCRIBERS_CATEGORY = int(os.getenv('MIN_SUBSCRIBERS_CATEGORY', 10))
292 # maximum number of episode actions that the API processes immediatelly before
293 # returning the response. Larger requests will be handled in background.
294 # Handler can be set to None to disable
295 API_ACTIONS_MAX_NONBG = int(os.getenv('API_ACTIONS_MAX_NONBG', 100))
296 API_ACTIONS_BG_HANDLER = 'mygpo.api.tasks.episode_actions_celery_handler'
299 ADSENSE_CLIENT = os.getenv('ADSENSE_CLIENT', '')
301 ADSENSE_SLOT_BOTTOM = os.getenv('ADSENSE_SLOT_BOTTOM', '')
303 # we're running behind a proxy that sets the X-Forwarded-Proto header correctly
304 # see https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
305 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
308 # enabled access to staff-only areas with ?staff=<STAFF_TOKEN>
309 STAFF_TOKEN = os.getenv('STAFF_TOKEN', None)
311 # Flattr settings -- available after you register your app
312 FLATTR_KEY = os.getenv('FLATTR_KEY', '')
313 FLATTR_SECRET = os.getenv('FLATTR_SECRET', '')
315 # Flattr thing of the webservice. Will be flattr'd when a user sets
316 # the "Auto-Flattr gpodder.net" option
317 FLATTR_MYGPO_THING = os.getenv(
318 'FLATTR_MYGPO_THING',
319 'https://flattr.com/submit/auto?user_id=stefankoegl&url=http://gpodder.net'
322 # The User-Agent string used for outgoing HTTP requests
323 USER_AGENT = 'gpodder.net (+https://github.com/gpodder/mygpo)'
325 # Base URL of the website that is used if the actually used parameters is not
326 # available. Request handlers, for example, can access the requested domain.
327 # Code that runs in background can not do this, and therefore requires a
328 # default value. This should be set to something like 'http://example.com'
329 DEFAULT_BASE_URL = os.getenv('DEFAULT_BASE_URL', '')
332 ### Celery
334 BROKER_URL = os.getenv('BROKER_URL', 'redis://localhost')
335 CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
337 SERVER_EMAIL = os.getenv('SERVER_EMAIL', 'no-reply@example.com')
339 CELERY_TASK_RESULT_EXPIRES = 60 * 60 # 1h expiry time in seconds
341 CELERY_ACCEPT_CONTENT = ['pickle', 'json']
343 CELERY_SEND_TASK_ERROR_EMAILS = get_bool('CELERY_SEND_TASK_ERROR_EMAILS',
344 False)
346 BROKER_POOL_LIMIT = get_intOrNone('BROKER_POOL_LIMIT', 10)
348 ### Google API
350 GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID', '')
351 GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET', '')
353 # URL where users of the site can get support
354 SUPPORT_URL = os.getenv('SUPPORT_URL', '')
357 FEEDSERVICE_URL = os.getenv('FEEDSERVICE_URL', 'http://feeds.gpodder.net/')
359 # Elasticsearch settings
361 ELASTICSEARCH_SERVER = os.getenv('ELASTICSEARCH_SERVER', '127.0.0.1:9200')
362 ELASTICSEARCH_INDEX = os.getenv('ELASTICSEARCH_INDEX', 'mygpo')
363 ELASTICSEARCH_TIMEOUT = float(os.getenv('ELASTICSEARCH_TIMEOUT', '2'))
365 # time for how long an activation is valid; after that, an unactivated user
366 # will be deleted
367 ACTIVATION_VALID_DAYS = int(os.getenv('ACTIVATION_VALID_DAYS', 10))
370 OPBEAT = {
371 "ORGANIZATION_ID": os.getenv('OPBEAT_ORGANIZATION_ID', ''),
372 "APP_ID": os.getenv('OPBEAT_APP_ID', ''),
373 "SECRET_TOKEN": os.getenv('OPBEAT_SECRET_TOKEN', ''),
376 LOCALE_PATHS = [
377 os.path.abspath(os.path.join(BASE_DIR, 'locale')),
380 INTERNAL_IPS = os.getenv('INTERNAL_IPS', '').split()
382 EMAIL_BACKEND = os.getenv('EMAIL_BACKEND',
383 'django.core.mail.backends.smtp.EmailBackend')
385 PODCAST_AD_ID = os.getenv('PODCAST_AD_ID')
387 TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
389 NOSE_ARGS = [
390 '--with-doctest',
391 '--stop',
392 '--where=mygpo',