├── .gitignore ├── LICENSE ├── Procfile ├── README.md ├── helloworld ├── __init__.py ├── settings.py ├── urls.py ├── views.py └── wsgi.py ├── manage.py ├── requirements.txt └── runtime.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *sqlite3 3 | staticfiles 4 | venv/ 5 | .env 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn --bind 0.0.0.0:${PORT:-8000} helloworld.wsgi 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Quick Start Guide 2 | 3 | This guide will walk you through deploying a Python / [Django](https://www.djangoproject.com/) application on [Deis Workflow][]. 4 | 5 | ## Usage 6 | 7 | ```console 8 | $ git clone https://github.com/deis/example-python-django.git 9 | $ cd example-python-django 10 | $ deis create 11 | Creating Application... done, created italic-rucksack 12 | Git remote deis added 13 | remote available at ssh://git@deis-builder.deis.rocks:2222/italic-rucksack.git 14 | $ git push deis master 15 | Counting objects: 75, done. 16 | Delta compression using up to 4 threads. 17 | Compressing objects: 100% (46/46), done. 18 | Writing objects: 100% (75/75), 12.01 KiB | 0 bytes/s, done. 19 | Total 75 (delta 31), reused 53 (delta 21) 20 | Starting build... but first, coffee! 21 | -----> Python app detected 22 | -----> Installing python-3.5.2 23 | $ pip install -r requirements.txt 24 | Collecting Django==1.10.0 (from -r requirements.txt (line 1)) 25 | Downloading Django-1.10-py2.py3-none-any.whl (6.8MB) 26 | Collecting gunicorn==19.6.0 (from -r requirements.txt (line 2)) 27 | Downloading gunicorn-19.6.0-py2.py3-none-any.whl (114kB) 28 | Installing collected packages: Django, gunicorn 29 | Successfully installed Django-1.10.0 gunicorn-19.6.0 30 | 31 | $ python manage.py collectstatic --noinput 32 | 56 static files copied to '/app/staticfiles'. 33 | 34 | -----> Discovering process types 35 | Procfile declares types -> web 36 | -----> Compiled slug size is 61M 37 | Build complete. 38 | Launching App... 39 | Done, italic-rucksack:v2 deployed to Workflow 40 | 41 | Use 'deis open' to view this application in your browser 42 | 43 | To learn more, use 'deis help' or visit https://deis.com/ 44 | 45 | To ssh://git@deis-builder.deis.rocks:2222/italic-rucksack.git 46 | * [new branch] master -> master 47 | $ curl http://italic-rucksack.deis.rocks 48 | Powered by Deis 49 | Release v2 on italic-rucksack-web-1653109058-vjlh0 50 | ``` 51 | 52 | ## Additional Resources 53 | 54 | * [GitHub Project](https://github.com/deis/workflow) 55 | * [Documentation](https://deis.com/docs/workflow/) 56 | * [Blog](https://deis.com/blog/) 57 | 58 | [Deis Workflow]: https://github.com/deis/workflow#readme 59 | -------------------------------------------------------------------------------- /helloworld/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deis/example-python-django/30eb071da4b4cf2134bf0d9016d0f44633792d70/helloworld/__init__.py -------------------------------------------------------------------------------- /helloworld/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for helloworld project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.10. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.10/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '4e&6aw+(5&cg^_!05r(&7_#dghg_pdgopq(yk)xa^bog7j)^*j' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = ['*'] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | ] 41 | 42 | MIDDLEWARE = [ 43 | 'django.middleware.security.SecurityMiddleware', 44 | 'django.contrib.sessions.middleware.SessionMiddleware', 45 | 'django.middleware.common.CommonMiddleware', 46 | 'django.middleware.csrf.CsrfViewMiddleware', 47 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 48 | 'django.contrib.messages.middleware.MessageMiddleware', 49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 50 | ] 51 | 52 | ROOT_URLCONF = 'helloworld.urls' 53 | 54 | TEMPLATES = [ 55 | { 56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 57 | 'DIRS': [], 58 | 'APP_DIRS': True, 59 | 'OPTIONS': { 60 | 'context_processors': [ 61 | 'django.template.context_processors.debug', 62 | 'django.template.context_processors.request', 63 | 'django.contrib.auth.context_processors.auth', 64 | 'django.contrib.messages.context_processors.messages', 65 | ], 66 | }, 67 | }, 68 | ] 69 | 70 | WSGI_APPLICATION = 'helloworld.wsgi.application' 71 | 72 | 73 | # Database 74 | # https://docs.djangoproject.com/en/1.10/ref/settings/#databases 75 | 76 | DATABASES = { 77 | 'default': { 78 | 'ENGINE': 'django.db.backends.sqlite3', 79 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 80 | } 81 | } 82 | 83 | 84 | # Password validation 85 | # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators 86 | 87 | AUTH_PASSWORD_VALIDATORS = [ 88 | { 89 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 90 | }, 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 99 | }, 100 | ] 101 | 102 | 103 | # Internationalization 104 | # https://docs.djangoproject.com/en/1.10/topics/i18n/ 105 | 106 | LANGUAGE_CODE = 'en-us' 107 | 108 | TIME_ZONE = 'UTC' 109 | 110 | USE_I18N = True 111 | 112 | USE_L10N = True 113 | 114 | USE_TZ = True 115 | 116 | 117 | # Static files (CSS, JavaScript, Images) 118 | # https://docs.djangoproject.com/en/1.10/howto/static-files/ 119 | 120 | STATIC_URL = '/static/' 121 | STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 122 | -------------------------------------------------------------------------------- /helloworld/urls.py: -------------------------------------------------------------------------------- 1 | """helloworld URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.10/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf.urls import url 17 | from django.contrib import admin 18 | from . import views 19 | 20 | urlpatterns = [ 21 | url(r'^admin/', admin.site.urls), 22 | url(r'^healthz', views.healthz, name='healthz'), 23 | url(r'^$', views.index, name='index'), 24 | ] 25 | -------------------------------------------------------------------------------- /helloworld/views.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | from django.http import HttpResponse 5 | 6 | 7 | def index(request): 8 | whom = os.getenv('POWERED_BY', 'Deis') 9 | release = os.getenv('WORKFLOW_RELEASE', 'unknown') 10 | container = subprocess.getoutput('hostname').strip() 11 | return HttpResponse('Powered by {whom}\nRelease {release} on {container}'.format(**locals())) 12 | 13 | 14 | # Return 200 for kubernetes healthcheck. 15 | def healthz(request): 16 | return HttpResponse('') 17 | -------------------------------------------------------------------------------- /helloworld/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for helloworld project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "helloworld.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "helloworld.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.10.6 2 | gunicorn==19.6.0 3 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.5.2 2 | --------------------------------------------------------------------------------