diff --git a/.env-local b/.env-local index 2d54eb0b..b2e1f829 100644 --- a/.env-local +++ b/.env-local @@ -1,5 +1,5 @@ -DATABASE_URL=postgres://postgres@database_default:5432/db +DATABASE_URL=postgres://postgres:password@database_default:5432/db DEFAULT_STORAGE_DSN=file:///data/media/?url=%2Fmedia%2F -DJANGO_DEBUG=True +DEBUG=True DOMAIN_ALIASES=localhost, 127.0.0.1 SECURE_SSL_REDIRECT=False diff --git a/.gitignore b/.gitignore index 61b0e5d6..e53bf1c4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ db.sqlite3 # Django -/staticfiles +/staticfiles_collected/ # Divio .divio @@ -18,3 +18,5 @@ db.sqlite3 ._* .Spotlight-V100 .Trashes + +.idea/ diff --git a/Dockerfile b/Dockerfile index a3b8f991..10bcf34a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,4 +3,4 @@ WORKDIR /app COPY . /app RUN pip install -r requirements.txt RUN python manage.py collectstatic --noinput -CMD uwsgi --http=0.0.0.0:80 --module=quickstart.wsgi +CMD uwsgi --http=0.0.0.0:80 --module=backend.wsgi diff --git a/README.md b/README.md index cd64467a..404183be 100644 --- a/README.md +++ b/README.md @@ -18,17 +18,12 @@ You need to have docker installed on your system to run this project. ```bash git clone git@github.com:django-cms/django-cms-quickstart.git cd django-cms-quickstart -docker-compose build -docker-compose run web python manage.py migrate -docker-compose run web python manage.py createsuperuser -docker-compose up -open http://127.0.0.1:8000 +docker compose up --force-recreate --build -d +docker compose run web python manage.py migrate +docker compose run web python manage.py createsuperuser ``` -For a more complete how-to guide to this project, see [Deploy a new django CMS project using the Divio quickstart -repository](https://docs.divio.com/en/latest/how-to/django-cms-deploy-quickstart/) in the [Divio Developer -Handbook](https://docs.divio.com). - +Then open http://django-cms-quickstart.127.0.0.1.nip.io:8000 (or just http://127.0.0.1:8000) in your browser. ## Customising the project @@ -40,8 +35,35 @@ see sections that can be removed - in each case, the section is noted with a com Options are also available for using Postgres/MySQL, uWSGI/Gunicorn/Guvicorn, etc. +## Features + +### Static Files with Whitenoise + +This quickstart demo has a cloud-ready static files setup via django-whitenoise. + +In the containerized cloud the application is not served by a web server like nginx but directly through uwsgi. django-whitenoise is the glue that's needed to serve static files in your application directly through uwsgi. + +See the django-whitenoise settings in settings.py and the `quickstart/templates/whitenoise-static-files-demo.html` demo page template that serves a static file. + ## Contribution -This code for this project has been forked from Divio's quickstart repo. We are grateful for their valueable contribution to the code and documentation of this code. +Here is the official django CMS repository: [https://github.com/django-cms/django-cms-quickstart/](https://github.com/django-cms/django-cms-quickstart/). + + +## Deployment + +Note that this is just a demo project to get you started. If you want a full production ready site with all the bells and whistles we recommend you have a look at https://github.com/django-cms/djangocms-template instead. + +#### Env variables +- to deploy this project in testing mode (recommended) set the environment variable `DEBUG` to `True` in your hosting environment. +- For production environment (if `DEBUG` is false) django requires you to whitelist the domain. Set the env var `DOMAIN` to the host, i.e. `www.domain.com` or `*.domain.com`. +- If you want the media hosted on S3 set the `DEFAULT_FILE_STORAGE` variable accordingly. + +#### Deployment Commands +Configure your hosting environment to run the following commands on every deployment: +- `./manage.py migrate` + + +#### Divio Deployment -You can follow the original repo [here](https://github.com/divio/django-cms-divio-quickstart/). +divio.com is a cloud hosting platform optimized for django web applications. It's the quickest way to deploy this project. Here is a [video tutorial](https://www.youtube.com/watch?v=O2g5Wfoyp7Q) and a [description of the deployment steps](https://github.com/django-cms/djangocms-template/blob/mco-standalone/docs/deployment-divio.md#divio-project-setup) that are mostly applicable for this quickstart project. diff --git a/quickstart/__init__.py b/backend/__init__.py similarity index 100% rename from quickstart/__init__.py rename to backend/__init__.py diff --git a/quickstart/asgi.py b/backend/asgi.py similarity index 82% rename from quickstart/asgi.py rename to backend/asgi.py index 28075b01..eb8d7e09 100644 --- a/quickstart/asgi.py +++ b/backend/asgi.py @@ -11,6 +11,6 @@ from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quickstart.settings') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') application = get_asgi_application() diff --git a/quickstart/settings.py b/backend/settings.py similarity index 80% rename from quickstart/settings.py rename to backend/settings.py index ff297d59..b89cadb5 100644 --- a/quickstart/settings.py +++ b/backend/settings.py @@ -11,15 +11,11 @@ SECRET_KEY = os.environ.get('SECRET_KEY', '') # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = os.environ.get('DJANGO_DEBUG') == "True" +DEBUG = os.environ.get('DEBUG') == "True" -DIVIO_DOMAIN = os.environ.get('DOMAIN', '') -DIVIO_DOMAIN_ALIASES = [ - d.strip() - for d in os.environ.get('DOMAIN_ALIASES', '').split(',') - if d.strip() -] -ALLOWED_HOSTS = [DIVIO_DOMAIN] + DIVIO_DOMAIN_ALIASES +ALLOWED_HOSTS = [os.environ.get('DOMAIN'),] +if DEBUG: + ALLOWED_HOSTS = ["*",] # Redirect to HTTPS by default, unless explicitly disabled SECURE_SSL_REDIRECT = os.environ.get('SECURE_SSL_REDIRECT') != "False" @@ -30,7 +26,7 @@ # Application definition INSTALLED_APPS = [ - 'quickstart', + 'backend', # optional, but used in most projects 'djangocms_admin_style', @@ -40,6 +36,7 @@ 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', + 'whitenoise.runserver_nostatic', # http://whitenoise.evans.io/en/stable/django.html#using-whitenoise-in-development 'django.contrib.staticfiles', 'django.contrib.sites', @@ -100,7 +97,7 @@ 'cms.middleware.language.LanguageCookieMiddleware', ] -ROOT_URLCONF = 'quickstart.urls' +ROOT_URLCONF = 'backend.urls' TEMPLATES = [ { @@ -129,13 +126,14 @@ CMS_TEMPLATES = [ # a minimal template to get started with ('minimal.html', 'Minimal template'), + ('whitenoise-static-files-demo.html', 'Static File Demo'), # optional templates that extend base.html, to be used with Bootstrap 4 ('page.html', 'Page'), ('feature.html', 'Page with Feature') ] -WSGI_APPLICATION = 'quickstart.wsgi.application' +WSGI_APPLICATION = 'backend.wsgi.application' # Database @@ -144,39 +142,27 @@ # Configure database using DATABASE_URL; fall back to sqlite in memory when no # environment variable is available, e.g. during Docker build DATABASE_URL = os.environ.get('DATABASE_URL', 'sqlite://:memory:') - -if not os.environ.get('CI', False): - DATABASES = {'default': dj_database_url.parse(DATABASE_URL)} -else: - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'postgres', - 'USER': 'postgres', - 'PASSWORD': 'postgres', - 'HOST': '127.0.0.1', - 'PORT': '5432', - } - } +DATABASES = {'default': dj_database_url.parse(DATABASE_URL)} # Password validation # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators -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', - }, -] +if not DEBUG: + 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 @@ -201,7 +187,7 @@ # https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = '/static/' -STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles_collected') STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # Media files @@ -214,7 +200,7 @@ DefaultStorageClass = dsn_configured_storage_class('DEFAULT_STORAGE_DSN') # Django's DEFAULT_FILE_STORAGE requires the class name -DEFAULT_FILE_STORAGE = 'quickstart.settings.DefaultStorageClass' +DEFAULT_FILE_STORAGE = 'backend.settings.DefaultStorageClass' # only required for local file storage and serving, in development MEDIA_URL = 'media/' diff --git a/backend/static/django-cms-logo.png b/backend/static/django-cms-logo.png new file mode 100644 index 00000000..402be042 Binary files /dev/null and b/backend/static/django-cms-logo.png differ diff --git a/quickstart/templates/base.html b/backend/templates/base.html similarity index 100% rename from quickstart/templates/base.html rename to backend/templates/base.html diff --git a/quickstart/templates/feature.html b/backend/templates/feature.html similarity index 100% rename from quickstart/templates/feature.html rename to backend/templates/feature.html diff --git a/quickstart/templates/menu.html b/backend/templates/menu.html similarity index 100% rename from quickstart/templates/menu.html rename to backend/templates/menu.html diff --git a/quickstart/templates/minimal.html b/backend/templates/minimal.html similarity index 100% rename from quickstart/templates/minimal.html rename to backend/templates/minimal.html diff --git a/quickstart/templates/page.html b/backend/templates/page.html similarity index 100% rename from quickstart/templates/page.html rename to backend/templates/page.html diff --git a/backend/templates/whitenoise-static-files-demo.html b/backend/templates/whitenoise-static-files-demo.html new file mode 100644 index 00000000..bf02b563 --- /dev/null +++ b/backend/templates/whitenoise-static-files-demo.html @@ -0,0 +1,15 @@ +{% load cms_tags sekizai_tags static %} + + + {% page_attribute "page_title" %} + {% render_block "css" %} + + + {% cms_toolbar %} + + + + {% placeholder "content" %} + {% render_block "js" %} + + diff --git a/quickstart/urls.py b/backend/urls.py similarity index 65% rename from quickstart/urls.py rename to backend/urls.py index dc20becb..4d8bcc7b 100644 --- a/quickstart/urls.py +++ b/backend/urls.py @@ -10,4 +10,7 @@ if settings.DEBUG: urlpatterns.extend(static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)) -urlpatterns.append(path('', include('cms.urls'))) \ No newline at end of file +urlpatterns.append(path('', include('cms.urls'))) + +# the new django admin sidebar is bad UX in django CMS custom admin views. +admin.site.enable_nav_sidebar = False diff --git a/quickstart/wsgi.py b/backend/wsgi.py similarity index 73% rename from quickstart/wsgi.py rename to backend/wsgi.py index 45154efa..006352d8 100644 --- a/quickstart/wsgi.py +++ b/backend/wsgi.py @@ -1,5 +1,5 @@ """ -WSGI config for quickstart project. +WSGI config for backend project. It exposes the WSGI callable as a module-level variable named ``application``. @@ -11,6 +11,6 @@ from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quickstart.settings') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') application = get_wsgi_application() diff --git a/docker-compose.yml b/docker-compose.yml index 9520566e..08cdc5d4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,8 +20,11 @@ services: database_default: # Select one of the following db configurations for the database image: postgres:9.6-alpine + ports: + - "5432:5432" # allow your local dev env to connect to the db environment: POSTGRES_DB: "db" + POSTGRES_PASSWORD: "password" POSTGRES_HOST_AUTH_METHOD: "trust" SERVICE_MANAGER: "fsm-postgres" volumes: diff --git a/manage.py b/manage.py index 062e0a3c..eb6431e2 100755 --- a/manage.py +++ b/manage.py @@ -6,7 +6,7 @@ def main(): """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'quickstart.settings') + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/requirements.txt b/requirements.txt index 1709a8c3..59c2dd10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django>=3.1,<3.2 +django>=3.1,<3.2 # 3.2 has dark admin theme which looks bad in custom django CMS admin views dj-database-url==0.5.0 django-storage-url==0.5.0 whitenoise==5.2.0 @@ -9,8 +9,7 @@ psycopg2==2.8.5 uwsgi==2.0.19.1 # key requirements for django CMS -django-cms>=3.8,<3.9 -django-treebeard>=4.0,<5.0 +django-cms<4 django-classy-tags>=2.0 django-sekizai>=2.0 six