2015-12-20 19:23:33 +00:00
|
|
|
"""
|
|
|
|
|
Django settings for paperless project.
|
|
|
|
|
|
|
|
|
|
Generated by 'django-admin startproject' using Django 1.9.
|
|
|
|
|
|
|
|
|
|
For more information on this file, see
|
2017-05-27 08:49:03 +10:00
|
|
|
https://docs.djangoproject.com/en/1.10/topics/settings/
|
2015-12-20 19:23:33 +00:00
|
|
|
|
|
|
|
|
For the full list of settings and their values, see
|
2017-05-27 08:49:03 +10:00
|
|
|
https://docs.djangoproject.com/en/1.10/ref/settings/
|
2015-12-20 19:23:33 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
2016-03-03 17:59:27 +00:00
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
|
2017-01-14 18:03:42 +00:00
|
|
|
|
|
|
|
|
# Tap paperless.conf if it's available
|
|
|
|
|
if os.path.exists("/etc/paperless.conf"):
|
|
|
|
|
load_dotenv("/etc/paperless.conf")
|
2018-03-04 21:37:04 +01:00
|
|
|
elif os.path.exists("/usr/local/etc/paperless.conf"):
|
|
|
|
|
load_dotenv("/usr/local/etc/paperless.conf")
|
2017-01-14 18:03:42 +00:00
|
|
|
|
|
|
|
|
|
2018-09-13 15:19:25 +02:00
|
|
|
def __get_boolean(key, default="NO"):
|
2018-09-09 21:22:07 +01:00
|
|
|
"""
|
|
|
|
|
Return a boolean value based on whatever the user has supplied in the
|
|
|
|
|
environment based on whether the value "looks like" it's True or not.
|
|
|
|
|
"""
|
2018-09-13 15:19:25 +02:00
|
|
|
return bool(os.getenv(key, default).lower() in ("yes", "y", "1", "t", "true"))
|
2018-09-09 21:22:07 +01:00
|
|
|
|
|
|
|
|
|
2015-12-20 19:23:33 +00:00
|
|
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
|
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Quick-start development settings - unsuitable for production
|
2017-05-27 08:49:03 +10:00
|
|
|
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2017-01-14 17:18:27 +00:00
|
|
|
# The secret key has a default that should be fine so long as you're hosting
|
|
|
|
|
# Paperless on a closed network. However, if you're putting this anywhere
|
|
|
|
|
# public, you should change the key to something unique and verbose.
|
|
|
|
|
SECRET_KEY = os.getenv(
|
|
|
|
|
"PAPERLESS_SECRET_KEY",
|
|
|
|
|
"e11fl1oa-*ytql8p)(06fbj4ukrlo+n7k&q5+$1md7i+mge=ee"
|
|
|
|
|
)
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2017-01-14 18:03:42 +00:00
|
|
|
|
2015-12-20 19:23:33 +00:00
|
|
|
# SECURITY WARNING: don't run with debug turned on in production!
|
2018-09-13 15:19:25 +02:00
|
|
|
DEBUG = __get_boolean("PAPERLESS_DEBUG", "YES")
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2018-04-13 20:17:31 +01:00
|
|
|
LOGIN_URL = "admin:login"
|
2016-08-23 11:31:54 -04:00
|
|
|
|
2017-01-03 09:52:31 +00:00
|
|
|
ALLOWED_HOSTS = ["*"]
|
|
|
|
|
|
|
|
|
|
_allowed_hosts = os.getenv("PAPERLESS_ALLOWED_HOSTS")
|
|
|
|
|
if _allowed_hosts:
|
|
|
|
|
ALLOWED_HOSTS = _allowed_hosts.split(",")
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2017-08-20 14:13:23 +02:00
|
|
|
FORCE_SCRIPT_NAME = os.getenv("PAPERLESS_FORCE_SCRIPT_NAME")
|
2017-08-19 12:39:25 +02:00
|
|
|
|
2015-12-20 19:23:33 +00:00
|
|
|
# Application definition
|
|
|
|
|
|
|
|
|
|
INSTALLED_APPS = [
|
2016-02-14 16:09:52 +00:00
|
|
|
|
2017-01-29 19:43:35 +00:00
|
|
|
"django.contrib.auth",
|
|
|
|
|
"django.contrib.contenttypes",
|
|
|
|
|
"django.contrib.sessions",
|
|
|
|
|
"django.contrib.messages",
|
|
|
|
|
"django.contrib.staticfiles",
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2018-08-16 17:05:54 +08:00
|
|
|
"corsheaders",
|
2015-12-20 19:23:33 +00:00
|
|
|
"django_extensions",
|
|
|
|
|
|
2016-03-28 11:11:15 +01:00
|
|
|
"documents.apps.DocumentsConfig",
|
2017-03-25 16:21:46 +00:00
|
|
|
"reminders.apps.RemindersConfig",
|
2017-03-11 16:30:49 +00:00
|
|
|
"paperless_tesseract.apps.PaperlessTesseractConfig",
|
2018-08-30 23:32:41 -04:00
|
|
|
"paperless_text.apps.PaperlessTextConfig",
|
2016-02-14 16:09:52 +00:00
|
|
|
|
2017-01-29 19:43:35 +00:00
|
|
|
"django.contrib.admin",
|
|
|
|
|
|
2016-02-16 09:28:34 +00:00
|
|
|
"rest_framework",
|
2016-03-09 01:05:46 +00:00
|
|
|
"crispy_forms",
|
2018-07-08 16:06:57 +01:00
|
|
|
"django_filters",
|
2016-02-16 09:28:34 +00:00
|
|
|
|
2015-12-20 19:23:33 +00:00
|
|
|
]
|
|
|
|
|
|
2017-03-11 16:30:49 +00:00
|
|
|
if os.getenv("PAPERLESS_INSTALLED_APPS"):
|
|
|
|
|
INSTALLED_APPS += os.getenv("PAPERLESS_INSTALLED_APPS").split(",")
|
|
|
|
|
|
2018-08-29 00:04:48 +02:00
|
|
|
MIDDLEWARE = [
|
2015-12-20 19:23:33 +00:00
|
|
|
'django.middleware.security.SecurityMiddleware',
|
|
|
|
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
2018-08-16 17:05:54 +08:00
|
|
|
'corsheaders.middleware.CorsMiddleware',
|
2015-12-20 19:23:33 +00:00
|
|
|
'django.middleware.common.CommonMiddleware',
|
2018-02-08 08:46:33 -05:00
|
|
|
'django.middleware.csrf.CsrfViewMiddleware',
|
|
|
|
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
|
|
|
'django.contrib.messages.middleware.MessageMiddleware',
|
2015-12-20 19:23:33 +00:00
|
|
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
|
|
|
]
|
|
|
|
|
|
2018-08-16 21:29:03 +08:00
|
|
|
# We allow CORS from localhost:8080
|
2018-08-17 11:48:39 +08:00
|
|
|
CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "localhost:8080").split(","))
|
2018-08-16 17:05:54 +08:00
|
|
|
|
2018-05-28 12:56:06 +01:00
|
|
|
# If auth is disabled, we just use our "bypass" authentication middleware
|
|
|
|
|
if bool(os.getenv("PAPERLESS_DISABLE_LOGIN", "false").lower() in ("yes", "y", "1", "t", "true")):
|
2018-08-29 00:04:48 +02:00
|
|
|
_index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware")
|
|
|
|
|
MIDDLEWARE[_index] = "paperless.middleware.Middleware"
|
2018-02-08 08:46:33 -05:00
|
|
|
|
2015-12-20 19:23:33 +00:00
|
|
|
ROOT_URLCONF = 'paperless.urls'
|
|
|
|
|
|
|
|
|
|
TEMPLATES = [
|
|
|
|
|
{
|
|
|
|
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
|
|
|
'DIRS': [],
|
|
|
|
|
'APP_DIRS': True,
|
|
|
|
|
'OPTIONS': {
|
|
|
|
|
'context_processors': [
|
|
|
|
|
'django.template.context_processors.debug',
|
|
|
|
|
'django.template.context_processors.request',
|
|
|
|
|
'django.contrib.auth.context_processors.auth',
|
|
|
|
|
'django.contrib.messages.context_processors.messages',
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
WSGI_APPLICATION = 'paperless.wsgi.application'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Database
|
2017-05-27 08:49:03 +10:00
|
|
|
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
|
2015-12-20 19:23:33 +00:00
|
|
|
|
|
|
|
|
DATABASES = {
|
2016-01-10 22:45:15 +00:00
|
|
|
"default": {
|
|
|
|
|
"ENGINE": "django.db.backends.sqlite3",
|
2016-08-23 13:28:08 -04:00
|
|
|
"NAME": os.path.join(
|
2017-01-01 18:40:23 +00:00
|
|
|
os.getenv(
|
|
|
|
|
"PAPERLESS_DBDIR",
|
|
|
|
|
os.path.join(BASE_DIR, "..", "data")
|
|
|
|
|
),
|
|
|
|
|
"db.sqlite3"
|
|
|
|
|
)
|
2015-12-20 19:23:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-08-23 12:22:36 -04:00
|
|
|
|
2018-09-23 14:01:15 +01:00
|
|
|
if os.getenv("PAPERLESS_DBUSER"):
|
2016-01-10 13:40:26 +00:00
|
|
|
DATABASES["default"] = {
|
|
|
|
|
"ENGINE": "django.db.backends.postgresql_psycopg2",
|
2016-02-27 20:18:50 +00:00
|
|
|
"NAME": os.getenv("PAPERLESS_DBNAME", "paperless"),
|
|
|
|
|
"USER": os.getenv("PAPERLESS_DBUSER"),
|
2016-01-10 13:40:26 +00:00
|
|
|
}
|
2018-09-23 14:01:15 +01:00
|
|
|
if os.getenv("PAPERLESS_DBPASS"):
|
|
|
|
|
DATABASES["default"]["PASSWORD"] = os.getenv("PAPERLESS_DBPASS")
|
2018-12-02 15:20:29 -06:00
|
|
|
if os.getenv("PAPERLESS_DBHOST"):
|
|
|
|
|
DATABASES["default"]["HOST"] = os.getenv("PAPERLESS_DBHOST")
|
|
|
|
|
if os.getenv("PAPERLESS_DBPORT"):
|
|
|
|
|
DATABASES["default"]["PORT"] = os.getenv("PAPERLESS_DBPORT")
|
2015-12-20 19:23:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# Password validation
|
2017-05-27 08:49:03 +10:00
|
|
|
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
|
2015-12-20 19:23:33 +00:00
|
|
|
|
|
|
|
|
AUTH_PASSWORD_VALIDATORS = [
|
|
|
|
|
{
|
|
|
|
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Internationalization
|
2017-05-27 08:49:03 +10:00
|
|
|
# https://docs.djangoproject.com/en/1.10/topics/i18n/
|
2015-12-20 19:23:33 +00:00
|
|
|
|
|
|
|
|
LANGUAGE_CODE = 'en-us'
|
|
|
|
|
|
2017-01-07 15:12:45 -08:00
|
|
|
TIME_ZONE = os.getenv("PAPERLESS_TIME_ZONE", "UTC")
|
2015-12-20 19:23:33 +00:00
|
|
|
|
|
|
|
|
USE_I18N = True
|
|
|
|
|
|
|
|
|
|
USE_L10N = True
|
|
|
|
|
|
|
|
|
|
USE_TZ = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Static files (CSS, JavaScript, Images)
|
2017-05-27 08:49:03 +10:00
|
|
|
# https://docs.djangoproject.com/en/1.10/howto/static-files/
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2017-02-01 00:22:32 +01:00
|
|
|
STATIC_ROOT = os.getenv(
|
|
|
|
|
"PAPERLESS_STATICDIR", os.path.join(BASE_DIR, "..", "static"))
|
2016-08-23 14:48:13 -04:00
|
|
|
MEDIA_ROOT = os.getenv(
|
2017-01-01 18:40:23 +00:00
|
|
|
"PAPERLESS_MEDIADIR", os.path.join(BASE_DIR, "..", "media"))
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2018-04-13 20:18:00 +01:00
|
|
|
STATIC_URL = os.getenv("PAPERLESS_STATIC_URL", "/static/")
|
|
|
|
|
MEDIA_URL = os.getenv("PAPERLESS_MEDIA_URL", "/media/")
|
2015-12-20 19:23:33 +00:00
|
|
|
|
|
|
|
|
|
2018-11-03 10:25:51 +00:00
|
|
|
# Other
|
|
|
|
|
|
|
|
|
|
# Disable Django's artificial limit on the number of form fields to submit at
|
|
|
|
|
# once. This is a protection against overloading the server, but since this is
|
|
|
|
|
# a self-hosted sort of gig, the benefits of being able to mass-delete a tonne
|
|
|
|
|
# of log entries outweight the benefits of such a safeguard.
|
|
|
|
|
|
|
|
|
|
DATA_UPLOAD_MAX_NUMBER_FIELDS = None
|
|
|
|
|
|
|
|
|
|
|
2016-03-03 17:59:27 +00:00
|
|
|
# Paperless-specific stuff
|
|
|
|
|
# You shouldn't have to edit any of these values. Rather, you can set these
|
|
|
|
|
# values in /etc/paperless.conf instead.
|
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
2016-02-27 20:18:50 +00:00
|
|
|
# Logging
|
|
|
|
|
|
|
|
|
|
LOGGING = {
|
|
|
|
|
"version": 1,
|
|
|
|
|
"disable_existing_loggers": False,
|
|
|
|
|
"handlers": {
|
|
|
|
|
"consumer": {
|
|
|
|
|
"class": "documents.loggers.PaperlessLogger",
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"loggers": {
|
|
|
|
|
"documents": {
|
|
|
|
|
"handlers": ["consumer"],
|
|
|
|
|
"level": os.getenv("PAPERLESS_CONSUMER_LOG_LEVEL", "INFO"),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-01-23 02:28:39 +00:00
|
|
|
# The default language that tesseract will attempt to use when parsing
|
|
|
|
|
# documents. It should be a 3-letter language code consistent with ISO 639.
|
2017-01-07 23:27:10 -08:00
|
|
|
OCR_LANGUAGE = os.getenv("PAPERLESS_OCR_LANGUAGE", "eng")
|
2016-01-23 02:28:39 +00:00
|
|
|
|
2016-02-14 15:57:42 +01:00
|
|
|
# The amount of threads to use for OCR
|
2016-02-27 20:18:50 +00:00
|
|
|
OCR_THREADS = os.getenv("PAPERLESS_OCR_THREADS")
|
2016-02-14 15:57:42 +01:00
|
|
|
|
2018-01-30 20:13:35 +00:00
|
|
|
# OCR all documents?
|
2018-09-09 21:22:07 +01:00
|
|
|
OCR_ALWAYS = __get_boolean("PAPERLESS_OCR_ALWAYS")
|
2018-01-30 20:13:35 +00:00
|
|
|
|
2016-02-27 20:18:50 +00:00
|
|
|
# If this is true, any failed attempts to OCR a PDF will result in the PDF
|
|
|
|
|
# being indexed anyway, with whatever we could get. If it's False, the file
|
|
|
|
|
# will simply be left in the CONSUMPTION_DIR.
|
2018-09-09 21:22:07 +01:00
|
|
|
FORGIVING_OCR = __get_boolean("PAPERLESS_FORGIVING_OCR")
|
2015-12-20 19:23:33 +00:00
|
|
|
|
2016-01-23 02:28:39 +00:00
|
|
|
# GNUPG needs a home directory for some reason
|
2016-02-27 20:18:50 +00:00
|
|
|
GNUPG_HOME = os.getenv("HOME", "/tmp")
|
2016-01-23 02:28:39 +00:00
|
|
|
|
2016-03-01 22:37:42 +00:00
|
|
|
# Convert is part of the ImageMagick package
|
2017-01-01 22:44:04 +00:00
|
|
|
CONVERT_BINARY = os.getenv("PAPERLESS_CONVERT_BINARY", "convert")
|
2016-03-25 20:31:15 +00:00
|
|
|
CONVERT_TMPDIR = os.getenv("PAPERLESS_CONVERT_TMPDIR")
|
|
|
|
|
CONVERT_MEMORY_LIMIT = os.getenv("PAPERLESS_CONVERT_MEMORY_LIMIT")
|
2016-05-13 22:47:40 -04:00
|
|
|
CONVERT_DENSITY = os.getenv("PAPERLESS_CONVERT_DENSITY")
|
2016-01-23 02:28:39 +00:00
|
|
|
|
2018-10-07 14:56:38 +01:00
|
|
|
# OptiPNG
|
|
|
|
|
OPTIPNG_BINARY = os.getenv("PAPERLESS_OPTIPNG_BINARY", "optipng")
|
|
|
|
|
|
2016-02-16 10:49:55 +01:00
|
|
|
# Unpaper
|
|
|
|
|
UNPAPER_BINARY = os.getenv("PAPERLESS_UNPAPER_BINARY", "unpaper")
|
|
|
|
|
|
2016-01-23 02:28:39 +00:00
|
|
|
# This will be created if it doesn't exist
|
2016-03-01 22:37:42 +00:00
|
|
|
SCRATCH_DIR = os.getenv("PAPERLESS_SCRATCH_DIR", "/tmp/paperless")
|
2016-01-23 02:28:39 +00:00
|
|
|
|
|
|
|
|
# This is where Paperless will look for PDFs to index
|
2016-03-01 22:37:42 +00:00
|
|
|
CONSUMPTION_DIR = os.getenv("PAPERLESS_CONSUMPTION_DIR")
|
2016-01-10 13:40:26 +00:00
|
|
|
|
2018-05-11 14:01:21 +02:00
|
|
|
# (This setting is ignored on Linux where inotify is used instead of a
|
|
|
|
|
# polling loop.)
|
2017-01-01 18:41:06 +00:00
|
|
|
# The number of seconds that Paperless will wait between checking
|
|
|
|
|
# CONSUMPTION_DIR. If you tend to write documents to this directory very
|
|
|
|
|
# slowly, you may want to use a higher value than the default.
|
|
|
|
|
CONSUMER_LOOP_TIME = int(os.getenv("PAPERLESS_CONSUMER_LOOP_TIME", 10))
|
|
|
|
|
|
2018-05-27 23:20:04 +01:00
|
|
|
# Pre-2.x versions of Paperless stored your documents locally with GPG
|
|
|
|
|
# encryption, but that is no longer the default. This behaviour is still
|
|
|
|
|
# available, but it must be explicitly enabled by setting
|
|
|
|
|
# `PAPERLESS_PASSPHRASE` in your environment or config file. The default is to
|
|
|
|
|
# store these files unencrypted.
|
|
|
|
|
#
|
|
|
|
|
# Translation:
|
|
|
|
|
# * If you're a new user, you can safely ignore this setting.
|
|
|
|
|
# * If you're upgrading from 1.x, this must be set, OR you can run
|
|
|
|
|
# `./manage.py change_storage_type gpg unencrypted` to decrypt your files,
|
|
|
|
|
# after which you can unset this value.
|
2016-02-27 20:18:50 +00:00
|
|
|
PASSPHRASE = os.getenv("PAPERLESS_PASSPHRASE")
|
2016-02-05 00:23:36 +00:00
|
|
|
|
2016-03-28 19:47:11 +01:00
|
|
|
# Trigger a script after every successful document consumption?
|
2016-06-23 21:57:17 +02:00
|
|
|
PRE_CONSUME_SCRIPT = os.getenv("PAPERLESS_PRE_CONSUME_SCRIPT")
|
2016-06-24 16:49:32 +02:00
|
|
|
POST_CONSUME_SCRIPT = os.getenv("PAPERLESS_POST_CONSUME_SCRIPT")
|
2017-01-14 17:09:48 +00:00
|
|
|
|
2018-09-05 23:03:30 -04:00
|
|
|
# Whether to display a selected document inline, or download it as attachment:
|
2018-09-09 21:22:07 +01:00
|
|
|
INLINE_DOC = __get_boolean("PAPERLESS_INLINE_DOC")
|
2018-09-05 23:03:30 -04:00
|
|
|
|
2017-01-14 17:09:48 +00:00
|
|
|
# The number of items on each page in the web UI. This value must be a
|
|
|
|
|
# positive integer, but if you don't define one in paperless.conf, a default of
|
|
|
|
|
# 100 will be used.
|
|
|
|
|
PAPERLESS_LIST_PER_PAGE = int(os.getenv("PAPERLESS_LIST_PER_PAGE", 100))
|
2017-08-24 20:51:09 +10:00
|
|
|
|
|
|
|
|
FY_START = os.getenv("PAPERLESS_FINANCIAL_YEAR_START")
|
|
|
|
|
FY_END = os.getenv("PAPERLESS_FINANCIAL_YEAR_END")
|
2018-01-28 19:09:52 +01:00
|
|
|
|
|
|
|
|
# Specify the default date order (for autodetected dates)
|
|
|
|
|
DATE_ORDER = os.getenv("PAPERLESS_DATE_ORDER", "DMY")
|
2018-11-15 20:32:15 -05:00
|
|
|
FILENAME_DATE_ORDER = os.getenv("PAPERLESS_FILENAME_DATE_ORDER")
|
2018-09-13 15:19:25 +02:00
|
|
|
|
|
|
|
|
# Specify for how many years a correspondent is considered recent. Recent
|
|
|
|
|
# correspondents will be shown in a separate "Recent correspondents" filter as
|
|
|
|
|
# well. Set to 0 to disable this filter.
|
|
|
|
|
PAPERLESS_RECENT_CORRESPONDENT_YEARS = int(os.getenv(
|
|
|
|
|
"PAPERLESS_RECENT_CORRESPONDENT_YEARS", 0))
|