Skip to content

Commit

Permalink
Merge pull request #11 from ninech/python
Browse files Browse the repository at this point in the history
add Python/Django example application
  • Loading branch information
thirdeyenick authored Sep 6, 2023
2 parents ab00a95 + 6ee244e commit 61be3fe
Show file tree
Hide file tree
Showing 22 changed files with 418 additions and 1 deletion.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# deploio-examples

This repository hosts example apps for different languages and frameworks that
are being supported by deplo.io.
are being supported by deplo.io. Please also check out our [language specific
documentation](https://docs.nine.ch/docs/category/languages) for more details.

## Go

Expand Down Expand Up @@ -38,3 +39,26 @@ nctl create application symfony \
--git-url=https://github.com/ninech/deploio-examples \
--git-sub-path=php/symfony
```

## Python

The example provides a Django application which shows a random message on every
page reload. It uses a temporary local sqlite database. Please note that the
database will be recreated on every deployment or restart of the application
(all data will be lost), so it really just is useful for demonstration purposes.
For persistent data, please use a postgres or mysql external database. The
Django admin interface can be used to add messages. Just visit `https://<URL of
app>/admin` to access it and use the user credentials which you pass via the env
variables below to login.
Please also define the `SECRET_KEY` which is used to secure signed data and
should be kept secret.

```bash
nctl create application django-example \
--git-url=https://github.com/ninech/deploio-examples \
--git-sub-path=python/django \
--env=DJANGO_SU_NAME=admin \
[email protected] \
--env=DJANGO_SU_PASSWORD=<INSERT A PASSWORD HERE> \
--env=SECRET_KEY=<VERY LONG RANDOM SECRET KEY>
```
2 changes: 2 additions & 0 deletions python/django/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
*.py[cod]
1 change: 1 addition & 0 deletions python/django/Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: python manage.py migrate && python manage.py makemigrations && gunicorn deploio.wsgi
Empty file.
16 changes: 16 additions & 0 deletions python/django/deploio/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for deploio project.
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/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'deploio.settings')

application = get_asgi_application()
131 changes: 131 additions & 0 deletions python/django/deploio/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""
Django settings for deploio project.
Generated by 'django-admin startproject' using Django 4.2.4.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""

from pathlib import Path
import os

# 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/

# SECURITY WARNING: keep the secret key used in production secret!
# The secret key can be passed via the env variable "SECRET_KEY"
SECRET_KEY = os.environ.get('SECRET_KEY')
if SECRET_KEY == None:
raise ValueError("SECRET_KEY environment variable must be set")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = [
".deploio.app",
"127.0.0.1",
]


# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
]

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'deploio.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 = 'deploio.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': '/tmp/db.sqlite3',
}
}


# Password validation
# https://docs.djangoproject.com/en/4.2/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',
},
]


# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
23 changes: 23 additions & 0 deletions python/django/deploio/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
URL configuration for deploio project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
path('admin/', admin.site.urls),
path("", include("index.urls")),
]
16 changes: 16 additions & 0 deletions python/django/deploio/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
WSGI config for deploio project.
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/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'deploio.settings')

application = get_wsgi_application()
Empty file added python/django/index/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions python/django/index/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from django.contrib import admin
from index.models import WelcomeMessage

admin.site.register(WelcomeMessage)
6 changes: 6 additions & 0 deletions python/django/index/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class IndexConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'index'
35 changes: 35 additions & 0 deletions python/django/index/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 4.2.5 on 2023-09-05 13:15

import os
from django.db import migrations


class Migration(migrations.Migration):

dependencies = []

def generate_superuser(apps, schema_editor):
from django.contrib.auth.models import User

DJANGO_SU_NAME = os.environ.get('DJANGO_SU_NAME')
DJANGO_SU_EMAIL = os.environ.get('DJANGO_SU_EMAIL')
DJANGO_SU_PASSWORD = os.environ.get('DJANGO_SU_PASSWORD')
if ( DJANGO_SU_NAME == None or
DJANGO_SU_EMAIL == None or
DJANGO_SU_PASSWORD == None
):
raise ValueError("environment variables DJANGO_SU_NAME, DJANGO_SU_EMAIL and DJANGO_SU_PASSWORD net to be set")

# only add the superuser if no other user exists
users = User.objects.all()
if not users:
superuser = User.objects.create_superuser(
username=DJANGO_SU_NAME,
email=DJANGO_SU_EMAIL,
password=DJANGO_SU_PASSWORD)

superuser.save()

operations = [
migrations.RunPython(generate_superuser),
]
22 changes: 22 additions & 0 deletions python/django/index/migrations/0002_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 4.2.5 on 2023-09-05 14:04

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
('index', '0001_initial'),
]

operations = [
migrations.CreateModel(
name='WelcomeMessage',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.CharField(max_length=160)),
],
),
]
19 changes: 19 additions & 0 deletions python/django/index/migrations/0003_add_welcome_messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.2.5 on 2023-09-05 14:53

from django.db import migrations

def add_welcome_messages(apps, schema_editor):
WelcomeMessage = apps.get_model("index", "WelcomeMessage")
for msg in ["Welcome to deplo.io", "Deployments made easy", "This is a sample Django app"]:
temp = WelcomeMessage(text=msg)
temp.save()

class Migration(migrations.Migration):

dependencies = [
('index', '0002_initial'),
]

operations = [
migrations.RunPython(add_welcome_messages),
]
Empty file.
4 changes: 4 additions & 0 deletions python/django/index/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from django.db import models

class WelcomeMessage(models.Model):
text = models.CharField(max_length=160)
44 changes: 44 additions & 0 deletions python/django/index/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>

<html lang="en">

<head>
<meta charset="UTF-8" />
<title>Django App on deplo.io</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="description" content="" />
<meta name="theme-color" content="">

<style>
body {
background-color: #141d50;
color: #ffffff;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
'Droid Sans', 'Helvetica Neue', 'Segoe UI Emoji',
'Apple Color Emoji', 'Noto Color Emoji', sans-serif;
}
.logo {
filter: invert(1);
width: 30%;
display: block;
margin-left: auto;
margin-right: auto;
}
.message {
width: 30%;
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
}
</style>
</head>

<body>
<h1 style="text-align:center">Django App</h1>
<img class="logo" src="https://docs.nine.ch/img/theme/deploio.svg"></img>
<p class="message">{{ message.text }}</p>
</body>

</html>
3 changes: 3 additions & 0 deletions python/django/index/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
7 changes: 7 additions & 0 deletions python/django/index/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path

from . import views

urlpatterns = [
path("", views.index, name="index"),
]
Loading

0 comments on commit 61be3fe

Please sign in to comment.