diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index da2c700..440d5da 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,27 +1,19 @@ # Code of Conduct -In this open-source project, our aim is to foster a welcoming and inclusive environment. We expect all contributors -and participants interact with each other with courtesy, respect and kindness. +## Welcome to Our Open-Source Community -We will not tolerate abuse or harassment of any kind. +This collaborative project strives to create an inclusive and welcoming environment. We value all contributors' and participants' interactions that reflect courtesy, respect, and kindness. -In the event of a concern about behaviour, please contact the maintainers of the project: +We have a zero-tolerance policy for any form of abuse or harassment. -* Dennis Schwertel +If you have concerns about behaviour, please reach out to Divio at info@divio.com. -Reports will be taken seriously and treated in confidence. If necessary, the maintainers will act to exclude -individuals from participating in this and other projects. +Reports will be treated confidentially and taken seriously. The project maintainers may take appropriate action, including exclusion from participation in this and other projects, if necessary. +## Guidelines for Code Review -## Code review +Code review is a crucial but sometimes challenging process for contributors and reviewers. It involves constructive critique, and improvements are often needed before accepting contributions. -Code review can be a frustrating process for both contributors and reviewers, with many opportunities for mutual -misunderstanding. +We expect contributors to recognize that all aspects of their submissions, including code and underlying ideas, will be carefully reviewed. -We expect participants who submit contributions for review to understand and accept that all contributions to the -project, including code and the ideas behind it, will be reviewed carefully. Often review will include critique and -criticism, and will almost always require improvements or other changes before contributions can be accepted. - -We also expect reviewers to communicate sensitively and respectfully. - -This is in line with a shared aim for the success of the project. +Reviewers are encouraged to provide feedback sensitively and respectfully, aligning with our shared goal for the project's success. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 017ebd5..3728fa0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,32 +1,26 @@ -# How to contribute to the project +# Contributing to the Project -Thanks for contributing, welcome aboard. +Thank you for contributing! We appreciate your involvement in making this project better. Before you start, please familiarize yourself with our [Code of Conduct](./CODE_OF_CONDUCT.md). -Please see our [CODE OF CONDUCT](./CODE_OF_CONDUCT.md) for our code of conduct. +## Submitting Proposals +Proposals can be submitted through: -## Submitting proposals +- [Pull Requests](https://github.com/divio/getting-started-with-django/pulls) +- [Issues](https://github.com/divio/getting-started-with-django/issues) -Please provide proposals as -[pull requests](https://github.com/divio/getting-started-with-django/pulls) -or -[issues](https://github.com/divio/getting-started-with-django/issues) as appropriate. +## Pull Requests and Branches +When making pull requests, adhere to the following: -## Pull requests and branches +- Submit from a properly named new branch. +- Target the `main` branch. -Please make pull requests: - -* from an appropriately-named new branch -* to the ``main`` branch - -See: - -* [how to make pull requests](https://help.github.com/articles/using-pull-requests/) -* [how to manage branches](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) +Learn more: +- [How to make pull requests](https://help.github.com/articles/using-pull-requests/) +- [Managing branches](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) ### Whitespace -Do not use trailing whitespace (spaces or tabs at the end of a line). They are often not visible, and can cause silent -problems and misleading unexpected changes. For example, some editors quietly delete them by default. +Avoid trailing whitespace (spaces or tabs at the end of a line). They might be invisible and lead to silent issues or unexpected changes. Some editors may silently delete them by default. diff --git a/Dockerfile b/Dockerfile index a9025ba..c76f57c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM python:3.12 # Set environment variables for Python -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 # Set the working directory to /app WORKDIR /app @@ -24,13 +24,12 @@ RUN pip-compile requirements.in && \ # Copy the rest of the project files into the container COPY . /app/ -RUN chmod +x manage.py # Run collectstatic to gather static files RUN python manage.py collectstatic --noinput -# Make port 8000 available to the world outside this container -EXPOSE 8000 +# Make port 80 available to the world outside this container +EXPOSE 80 # Define the command to run your application -CMD ["gunicorn", "wsgi:application", "--bind", "0.0.0.0:8000"] +CMD ["gunicorn", "mysite.wsgi:application", "--bind", "0.0.0.0:80"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..40b943b --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2024, Divio AG +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Divio AG nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DIVIO AG BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index e18beea..03e00b9 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,28 @@ -# Getting started with Django +# Getting Started with Django -[![Deploy at Divio -badge](https://img.shields.io/badge/deploy%20at%20divio-DFFF67)](https://control.divio.com/app/new/?template_url=https://github.com/divio/getting-started-with-django/archive/refs/heads/main.zip) +[![Deploy to Divio](https://img.shields.io/badge/DEPLOY-TO%20DIVIO-DFFF67?logo=docker&logoColor=white&labelColor=333333)](https://control.divio.com/app/new/?template_url=https://github.com/divio/getting-started-with-django/archive/refs/heads/main.zip) +Welcome to our QuickStart template – your portal to swift application development and seamless local testing. Whether you're delving into Django for the first time or optimizing your workflow, our template, based on Djangos' [Getting started](https://docs.djangoproject.com/en/5.0/intro/) guide, has got you covered. -This is a template project to bootstrap a Django application. +## Cloud Setup +Use the app creation wizard with a free [Divio Account](https://control.divio.com/) and choose **Django** from the template selection. Alternatively, click the `Deploy to Divio` button above and follow the app creation wizard. Finally, deploy your app to the `test` or `live` environment. -## Quick Start with Divio Cloud +Beware that the **admin** user is not created automatically. +You can do so by connecting via SSH and manually run `python manage.py createsuperuser`. -### Create a free Divio account -Create a free [Divio account](https://control.divio.com/). +For in-depth details about Divio Cloud, refer to the [Divio documentation](https://docs.divio.com/introduction/). -### Deploy your app in Divio Cloud -- Click the `Deploy at Divio` button above and provide the information requested by the app creation wizard (eg. app name and app settings) +## Local Setup -- In Divio Control Panel dashboard, Add `PostgreSQL` database under Services section. +Install the [Divio CLI](https://github.com/divio/divio-cli) to set up your app locally. -- Under settings, add the `Release Command` for database migration: - - `python manage.py migrate` -(`Release Commands` are the commands executed at the start of app container). +Alternatively, build this app locally using Docker: - -- Deploy an environment; test or live. Open the Env URL in your browser. - -For more details about Divio system, read [Divio documentation](https://docs.divio.com/introduction/) - - -## Setup your local development environment with Divio CLI - -Please follow our simple guidelines for [Divio CLI installation](https://docs.divio.com/introduction/01-installation/) and [setup local development](https://docs.divio.com/introduction/01-installation/#tutorial-installation&gsc.tab=0) - - -## Setup your local development environment without Divio CLI - -### Install Docker - -This project uses Docker and docker-compose which you can install from the [offical Docker website](https://docs.docker.com/get-docker/). - -### Clone the repository - -``` -git clone https://github.com/divio/getting-started-with-django.git -``` - -### Build the project - -Let's build the docker image of the project. -``` -cd getting-started-with-django -docker-compose build -``` - -### Run the project - -``` -docker-compose up -``` - -This command will start the `web` and `database_default` services. You can reach the web application at [http://localhost:8000]() and Admin panel at [http://localhost:8000/admin]() - - -To access admin, create a super user. -``` -docker-compose run web python manage.py createsuperuser -``` - -## How to develop - -Follow the official [Django development guides](https://docs.djangoproject.com/en/4.2/intro/tutorial01/) - - -## Contribute to the project - -See the [contribution guide](./CONTRIBUTING.md). +1. Ensure [Docker](https://docs.docker.com/get-docker/) is installed and running. +2. Clone this repository locally. +3. Build the app with `docker compose build`. +4. Run the migrations with `docker compose run --rm web python manage.py migrate` +5. Create a superuser with `docker compose run --rm web python manage.py createsuperuser` +6. Run the app using `docker compose up`. +7. Open [http://localhost:8000]() to view your app. diff --git a/docker-compose.yml b/docker-compose.yml index aa80034..f08a819 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,26 +1,19 @@ -version: '3' +version: "3" services: - web: - # the application's web service (container) will use an image based on our Dockerfile - build: "." - # Map the internal port 80 to port 8000 on the host + build: . ports: - "8000:80" - # Map the host directory to app (which allows us to see and edit files inside the container) volumes: - ".:/app:rw" - # The default command to run when launching the container - command: python manage.py runserver 0.0.0.0:80 - # a link to database_default, the application's local database service + environment: + DATABASE_URL: postgres://postgres@database_default:5432/db links: - "database_default" - # load environment variables from env file - env_file: ./localdev/.env.local + command: python manage.py runserver 0.0.0.0:80 database_default: - # the application's web service will use an off-the-shelf image image: postgres:13.5-alpine environment: POSTGRES_DB: "db" diff --git a/localdev/.env.local b/localdev/.env.local deleted file mode 100644 index eae6096..0000000 --- a/localdev/.env.local +++ /dev/null @@ -1,4 +0,0 @@ -DEBUG=True -SECRET_KEY=ny-i$#qn9y=^&d^ena6z9deou$ymsh+mev(1t8qi*jqdx+yyx -DATABASE_URL=postgres://postgres@database_default:5432/db -ALLOWED_HOSTS=localhost diff --git a/manage.py b/manage.py old mode 100755 new mode 100644 index 1b243ab..a7da667 --- a/manage.py +++ b/manage.py @@ -6,7 +6,7 @@ def main(): """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/__init__.py b/mysite/__init__.py similarity index 100% rename from __init__.py rename to mysite/__init__.py diff --git a/asgi.py b/mysite/asgi.py similarity index 61% rename from asgi.py rename to mysite/asgi.py index 9dfc4ce..a391ebd 100644 --- a/asgi.py +++ b/mysite/asgi.py @@ -1,16 +1,16 @@ """ -ASGI config for project. +ASGI config. It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ """ import os from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') application = get_asgi_application() diff --git a/settings.py b/mysite/settings.py similarity index 52% rename from settings.py rename to mysite/settings.py index db4090b..cf8b463 100644 --- a/settings.py +++ b/mysite/settings.py @@ -1,31 +1,36 @@ """ -Django settings for project. +Django settings. -Generated by 'django-admin startproject' using Django 4.2. +Generated by 'django-admin startproject'. For more information on this file, see -https://docs.djangoproject.com/en/4.2/topics/settings/ +https://docs.djangoproject.com/en/5.0/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.2/ref/settings/ +https://docs.djangoproject.com/en/5.0/ref/settings/ """ import os + import dj_database_url -from pathlib import Path +from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'changeme' -DEBUG = os.getenv('DEBUG', default=False) -SECRET_KEY = os.getenv('SECRET_KEY') -ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', default='*').split(',') -CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', default='https://*.aldryn.io').split(',') +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ["*"] +CSRF_TRUSTED_ORIGINS=["https://*.aldryn.io"] # Application definition @@ -37,7 +42,7 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'sampleapp', + 'storages', ] MIDDLEWARE = [ @@ -50,12 +55,12 @@ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] -ROOT_URLCONF = 'urls' +ROOT_URLCONF = 'mysite.urls' -TEMPLATES = [ +TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR, 'templates')], + 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -68,19 +73,25 @@ }, ] -WSGI_APPLICATION = 'wsgi.application' +WSGI_APPLICATION = 'mysite.wsgi.application' # Database -# https://docs.djangoproject.com/en/4.2/ref/settings/#databases +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases -if os.environ.get('DATABASE_URL', default=None): - DATABASE_URL = os.environ.get('DATABASE_URL') - DATABASES = {'default': dj_database_url.parse(DATABASE_URL)} +if "DATABASE_URL" in os.environ: + DATABASES = {'default': dj_database_url.config(conn_max_age=500)} +else: + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } + } # Password validation -# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -99,7 +110,7 @@ # Internationalization -# https://docs.djangoproject.com/en/4.2/topics/i18n/ +# https://docs.djangoproject.com/en/5.0/topics/i18n/ LANGUAGE_CODE = 'en-us' @@ -111,12 +122,38 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/4.2/howto/static-files/ -STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' +# https://docs.djangoproject.com/en/5.0/howto/static-files/ + STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'staticfiles' + +# Default storage settings, with the staticfiles storage updated. +# See https://docs.djangoproject.com/en/5.0/ref/settings/#std-setting-STORAGES + +STORAGES = { + "default": { + "BACKEND": "storages.backends.s3boto3.S3Boto3Storage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + }, +} + + # Default primary key field type -# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + + +# AWS S3 storage configuration +AWS_ACCESS_KEY_ID = os.environ.get('DEFAULT_STORAGE_ACCESS_KEY_ID', '') +AWS_SECRET_ACCESS_KEY = os.environ.get('DEFAULT_STORAGE_SECRET_ACCESS_KEY', '') +AWS_S3_REGION_NAME = os.environ.get('DEFAULT_STORAGE_REGION', '') +AWS_STORAGE_BUCKET_NAME=os.environ.get('DEFAULT_STORAGE_BUCKET', '') +AWS_S3_CUSTOM_DOMAIN = os.environ.get('DEFAULT_STORAGE_CUSTOM_DOMAIN', '') +AWS_S3_OBJECT_PARAMETERS = { + 'ACL': 'public-read', + 'CacheControl': 'max-age=86400', +} diff --git a/urls.py b/mysite/urls.py similarity index 64% rename from urls.py rename to mysite/urls.py index 1e6483d..f095210 100644 --- a/urls.py +++ b/mysite/urls.py @@ -1,8 +1,8 @@ """ -URL configuration for project. +URL configuration. The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/4.2/topics/http/urls/ + https://docs.djangoproject.com/en/5.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views @@ -15,13 +15,8 @@ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path, include -from django.conf import settings -from django.conf.urls.static import static -from django.shortcuts import render - +from django.urls import path urlpatterns = [ path('admin/', admin.site.urls), - path('', include('sampleapp.urls')), -]+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +] diff --git a/wsgi.py b/mysite/wsgi.py similarity index 61% rename from wsgi.py rename to mysite/wsgi.py index 83d49ef..4771ef1 100644 --- a/wsgi.py +++ b/mysite/wsgi.py @@ -1,16 +1,16 @@ """ -WSGI config for project. +WSGI config. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') application = get_wsgi_application() diff --git a/requirements.in b/requirements.in index 41aabf4..c5a6240 100644 --- a/requirements.in +++ b/requirements.in @@ -1,5 +1,6 @@ -Django==4.2 -gunicorn==20.1 -psycopg==3.1.14 -python-dotenv==0.19.1 +Django>=4.2,<5.1 dj-database-url==2.1.0 +psycopg[binary]>=3.1,<3.2 +gunicorn>=21.2 +django-storages>=1.14 +boto3>=1.34 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 4c1f01d..0000000 --- a/requirements.txt +++ /dev/null @@ -1,29 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.12 -# by the following command: -# -# pip-compile requirements.in -# -asgiref==3.7.2 - # via django -dj-database-url==2.1.0 - # via -r requirements.in -django==4.2 - # via - # -r requirements.in - # dj-database-url -gunicorn==20.1.0 - # via -r requirements.in -psycopg==3.1.14 - # via -r requirements.in -python-dotenv==0.19.1 - # via -r requirements.in -sqlparse==0.4.4 - # via django -typing-extensions==4.9.0 - # via - # dj-database-url - # psycopg - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/sampleapp/__init__.py b/sampleapp/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/sampleapp/admin.py b/sampleapp/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/sampleapp/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/sampleapp/apps.py b/sampleapp/apps.py deleted file mode 100644 index c1646a6..0000000 --- a/sampleapp/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class SampleappConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'sampleapp' diff --git a/sampleapp/migrations/__init__.py b/sampleapp/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/sampleapp/models.py b/sampleapp/models.py deleted file mode 100644 index 71a8362..0000000 --- a/sampleapp/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/sampleapp/templates/home.html b/sampleapp/templates/home.html deleted file mode 100644 index 91d14d4..0000000 --- a/sampleapp/templates/home.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Divio Django template app - - - -

Welcome to the home page!

-

- Django Admin -

- - - \ No newline at end of file diff --git a/sampleapp/tests.py b/sampleapp/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/sampleapp/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/sampleapp/urls.py b/sampleapp/urls.py deleted file mode 100644 index 9ec8361..0000000 --- a/sampleapp/urls.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.urls import path -from . import views - -urlpatterns = [ - path('', views.home, name='home'), -] diff --git a/sampleapp/views.py b/sampleapp/views.py deleted file mode 100644 index 0b21058..0000000 --- a/sampleapp/views.py +++ /dev/null @@ -1,4 +0,0 @@ -from django.shortcuts import render - -def home(request): - return render(request, 'home.html') \ No newline at end of file