diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e26903f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.*.swp + +*.py[cod] + +db.sqlite3 diff --git a/.s2i/action_hooks/build b/.s2i/action_hooks/build new file mode 100755 index 0000000..ceaac45 --- /dev/null +++ b/.s2i/action_hooks/build @@ -0,0 +1,37 @@ +#!/bin/bash + +# This is a 'build' action hook script. This script must be executable +# and will be run by the S2I process after the original S2I 'assemble' +# script has been run. This hook is to allow a user to run additional +# build steps which may need the source code or build artefacts in +# place, or to setup any data required for the application. + +set -eo pipefail + +# Dump out the set of environment variables which were used by the build. + +echo " -----> Initial environment variables set by builder image." + +env + +# Dump out the name of the current working directory. + +echo " -----> Current working directory." + +pwd + +# Run the application specific build steps for this project. + +echo " -----> Running collection of Django static resources." + +python manage.py collectstatic --noinput + +echo " -----> Creating directory for uploaded image files." + +mkdir -p media/images && chmod g+w media/images + +# Dump out the contents of the current working directory. + +echo " -----> Contents of the current working directory after build run." + +ls -R . diff --git a/.s2i/action_hooks/build_env b/.s2i/action_hooks/build_env new file mode 100644 index 0000000..140d6ea --- /dev/null +++ b/.s2i/action_hooks/build_env @@ -0,0 +1,17 @@ +# This is a 'build_env' action hook. This script will be executed inline +# to the custom 'assemble' script and therefore doesn't need to start +# with a '#!' line nor be marked as an executable file. This script will +# be interpreted as if it is a 'bash' script. This script can be used to +# dynamically set additional environment variables required by the build +# process. These might for example be environment variables which +# specify where third party libraries or packages installed from the +# 'pre_build' hook are located and which may be needed when building +# application artefacts. When we source the 'build_env' script, any +# environment variables set by it will be automatically exported. +# Although principally intended for setting environment variables, it +# can include other script logic, but this should be avoided exception +# to the extent it is required to work out what to set any environment +# variables to. + +BUILD_OVERRIDE_VALUE=value +BUILD_DEFAULT_VALUE=${BUILD_DEFAULT_VALUE:-default} diff --git a/.s2i/action_hooks/deploy b/.s2i/action_hooks/deploy new file mode 100755 index 0000000..77028d2 --- /dev/null +++ b/.s2i/action_hooks/deploy @@ -0,0 +1,39 @@ +#!/bin/bash + +# This is a 'deploy' action hook script. This script must be executable +# and will be run by the S2I process just before the original S2I 'run' +# script is run. This script is to allow a user to run any final steps +# just before the application is to be started. This can include running +# background tasks. + +set -eo pipefail + +# Dump out the set of environment variables which were used by the build. + +echo " -----> Environment variables set for the deployed application." + +env + +# Dump out the name of the current working directory. + +echo " -----> Current working directory." + +pwd + +# Run the application specific deploy steps for this project. + +if [ x"$DATABASE_URL" != x"" ]; then + echo " -----> Running Django database table migrations." + + python manage.py migrate --noinput +else + DJANGO_ADMIN_USERNAME=developer \ + DJANGO_ADMIN_EMAIL=developer@example.com \ + DJANGO_ADMIN_PASSWORD=developer `dirname $0`/setup +fi + +# Dump out the contents of the current working directory. + +echo " -----> Contents of the current working directory after build run." + +ls -R . diff --git a/.s2i/action_hooks/deploy_env b/.s2i/action_hooks/deploy_env new file mode 100644 index 0000000..cf068fa --- /dev/null +++ b/.s2i/action_hooks/deploy_env @@ -0,0 +1,16 @@ +# This is a 'deploy_env' action hook. This script will be executed +# inline to the custom 'run' script as well as for any interactive shell +# if so enabled. As it is executed inline, it doesn't need to start with +# a '#!' line nor be marked as an executable file. This script will be +# interpreted as if it is a 'bash' script. This script allows a user to +# dynamically set additional environment variables required by the +# deploy process. These might for example be environment variables which +# tell an application where files it requires are located. When we +# source the 'deploy_env' script, any environment variables set by it +# will be automatically exported. Although principally intended for +# setting environment variables, it can include other script logic, but +# this should be avoided exception to the extent it is required to work +# out what to set any environment variables to. + +DEPLOY_OVERRIDE_VALUE=value +DEPLOY_DEFAULT_VALUE=${DEPLOY_DEFAULT_VALUE:-default} diff --git a/.s2i/action_hooks/pre_build b/.s2i/action_hooks/pre_build new file mode 100755 index 0000000..c7e8d2c --- /dev/null +++ b/.s2i/action_hooks/pre_build @@ -0,0 +1,36 @@ +#!/bin/bash + +# This is a 'pre_build' action hook script. This script must be +# executable and will be run by the S2I process as the very first step. +# This script can be used to install additional third party libraries +# or packages that may be required by the build process. If the +# 'pre_build' hook needs any files from the application source code, it +# must grab them from the '/tmp/src' directory as they will only be +# copied into place by the original S2I 'assemble' script later on in +# the build process. + +set -eo pipefail + +# Dump out the initial set of environment variables. + +echo " -----> Initial environment variables set by builder image." + +env + +# Dump out the contents of the '/tmp/src' directory. + +echo " -----> Initial contents of the /tmp/src directory." + +ls -R /tmp/src + +# Dump out the name of the current working directory. + +echo " -----> Current working directory." + +pwd + +# Dump out the contents of the current working directory. + +echo " -----> Initial contents of the current working directory." + +ls -R . diff --git a/.s2i/action_hooks/setup b/.s2i/action_hooks/setup new file mode 100755 index 0000000..dc11fd2 --- /dev/null +++ b/.s2i/action_hooks/setup @@ -0,0 +1,24 @@ +#!/bin/bash + +echo " -----> Running Django database table migrations." + +python manage.py migrate --noinput + +if [ x"$DJANGO_ADMIN_USERNAME" != x"" ]; then + echo " -----> Creating predefined Django super user" + (cat - | python manage.py shell) << ! +from django.contrib.auth.models import User; +User.objects.create_superuser('$DJANGO_ADMIN_USERNAME', + '$DJANGO_ADMIN_EMAIL', + '$DJANGO_ADMIN_PASSWORD') +! +else + if (tty > /dev/null 2>&1); then + echo " -----> Running Django super user creation" + python manage.py createsuperuser + fi +fi + +echo " -----> Pre-loading Django database with blog posts." + +python manage.py loaddata `dirname $0`/../../posts.json diff --git a/.s2i/bin/assemble b/.s2i/bin/assemble new file mode 100755 index 0000000..ac3a7a5 --- /dev/null +++ b/.s2i/bin/assemble @@ -0,0 +1,108 @@ +#!/bin/bash + +echo " -----> Running application assemble script." + +# Ensure we fail fast if there is a problem. + +set -eo pipefail + +# It is presumed the current working directory is where the application +# code will reside, or at least that this directory is writable and we +# can add our own files for hook scripts there. This would normally be +# the HOME directory for the builder account. + +S2I_SOURCE_PATH=`pwd` +export S2I_SOURCE_PATH + +# At this point the application source code is still located under the +# directory '/tmp/src'. The source code or application artefacts +# compiled from it will not be moved into place until the original +# 'assemble' script is run. What we will do at this point is move the +# contents of the '.s2i' directory across so that any hook scripts are +# where we need them to be. This shouldn't upset anything as the 's2i' +# program has already extracted out the '.s2i/bin' directory and other +# files it wants separately. + +test -d /tmp/src/.s2i && mv /tmp/src/.s2i . + +# Now run the 'pre_build' hook from the '.s2i/action_hooks' directory if +# it exists. This hook is to allow a user to install additional third +# party libraries or packages that may be required by the build process. +# If the 'pre_build' hook needs any files from the application source +# code, it must grab them from the '/tmp/src' directory. + +if [ -f $S2I_SOURCE_PATH/.s2i/action_hooks/pre_build ]; then + if [ ! -x $S2I_SOURCE_PATH/.s2i/action_hooks/pre_build ]; then + echo "WARNING: Script $S2I_SOURCE_PATH/.s2i/action_hooks/pre_build not executable." + else + echo " -----> Running $S2I_SOURCE_PATH/.s2i/action_hooks/pre_build" + $S2I_SOURCE_PATH/.s2i/action_hooks/pre_build + fi +fi + +# Now source the 'build_env' script from the '.s2i/action_hooks' +# directory if it exists. This script allows a user to dynamically set +# additional environment variables required by the build process. These +# might for example be environment variables which specify where third +# party libraries or packages installed form the 'pre_build' hook are +# located and which may be needed when building application artefacts. +# When we source the 'build_env' script, any environment variables set +# by it will be automatically exported. + +if [ -f $S2I_SOURCE_PATH/.s2i/action_hooks/build_env ]; then + echo " -----> Running $S2I_SOURCE_PATH/.s2i/action_hooks/build_env" + S2I_SHELL_PWD=$PWD + set -a; . $S2I_SOURCE_PATH/.s2i/action_hooks/build_env; set +a + cd $S2I_SHELL_PWD +fi + +# Now run the original 'assemble' script. This will move source code into +# the correct location or otherwise build application artefacts from the +# source code and move that into place. + +echo " -----> Running builder assemble script ($S2I_SCRIPTS_PATH/assemble)" + +$S2I_SCRIPTS_PATH/assemble + +# Now run the 'build' hook from '.s2i/action_hooks' directory if it +# exists. This hook is to allow a user to run additional build steps +# which may need the source code or build artefacts in place, or to +# setup any data required for the application. + +if [ -f $S2I_SOURCE_PATH/.s2i/action_hooks/build ]; then + if [ ! -x $S2I_SOURCE_PATH/.s2i/action_hooks/build ]; then + echo "WARNING: Script $S2I_SOURCE_PATH/.s2i/action_hooks/build not executable." + else + echo " -----> Running $S2I_SOURCE_PATH/.s2i/action_hooks/build" + $S2I_SOURCE_PATH/.s2i/action_hooks/build + fi +fi + +# Now fix up the shell login environment so it will trigger 'deploy_env'. + +if [ x"$S2I_BASH_ENV" != x"" ]; then + if [ -f $S2I_BASH_ENV ]; then + cat >> $S2I_BASH_ENV << EOF +# Now source the 'deploy_env' script from the '.s2i/action_hooks' +# directory if it exists. This script allows a user to dynamically set +# additional environment variables required by the deploy process. These +# might for example be environment variables which tell an application +# where files it requires are located. When we source the 'deploy_env' +# script, any environment variables set by it will be automatically +# exported. Note that we only source the 'deploy_env' script if it +# hasn't already been run. + +if [ x"S2I_MARKERS_ENVIRON" != x"" ]; then + S2I_MARKERS_ENVIRON=OK + export S2I_MARKERS_ENVIRON + + if [ -f $S2I_SOURCE_PATH/.s2i/action_hooks/deploy_env ]; then + S2I_SHELL_PWD=$PWD + cd $S2I_SOURCE_PATH + set -a; . $S2I_SOURCE_PATH/.s2i/action_hooks/deploy_env; set +a + cd $S2I_SHELL_PWD + fi +fi +EOF + fi +fi diff --git a/.s2i/bin/run b/.s2i/bin/run new file mode 100755 index 0000000..054d463 --- /dev/null +++ b/.s2i/bin/run @@ -0,0 +1,60 @@ +#!/bin/bash + +echo " -----> Running application run script." + +# Ensure we fail fast if there is a problem. + +set -eo pipefail + +# It is presumed the current working directory is where the application +# code will reside, or at least that this directory is writable and we +# can add our own files for hook scripts there. This would normally be +# the HOME directory for the builder account. + +S2I_SOURCE_PATH=`pwd` +export S2I_SOURCE_PATH + +# Now source the 'deploy_env' script from the '.s2i/action_hooks' +# directory if it exists. This script allows a user to dynamically set +# additional environment variables required by the deploy process. These +# might for example be environment variables which tell an application +# where files it requires are located. When we source the 'deploy_env' +# script, any environment variables set by it will be automatically +# exported. Note that we only source the 'deploy_env' script if it hasn't +# already been run. It could have already been run from the shell login +# environment. + +if [ x"S2I_MARKER_ENVIRON" != x"" ]; then + S2I_MARKER_ENVIRON=`date` + export S2I_MARKER_ENVIRON + + if [ -f $S2I_SOURCE_PATH/.s2i/action_hooks/deploy_env ]; then + echo " -----> Running $S2I_SOURCE_PATH/.s2i/action_hooks/deploy_env" + S2I_SHELL_PWD=$PWD + set -a; . $S2I_SOURCE_PATH/.s2i/action_hooks/deploy_env; set +a + cd $S2I_SHELL_PWD + fi +fi + +# Now run the 'deploy' hook from the '.s2i/action_hooks' directory if it +# exists. This hook is to allow a user to run any final steps just before +# the application is to be started. This can include running background +# tasks. + +if [ -f $S2I_SOURCE_PATH/.s2i/action_hooks/deploy ]; then + if [ ! -x $S2I_SOURCE_PATH/.s2i/action_hooks/deploy ]; then + echo "WARNING: Script $S2I_SOURCE_PATH/.s2i/action_hooks/deploy not executable." + else + echo " -----> Running $S2I_SOURCE_PATH/.s2i/action_hooks/deploy" + $S2I_SOURCE_PATH/.s2i/action_hooks/deploy + fi +fi + +# Now run the original 'run' script to start up the application. This +# must be run using 'exec' so that the original 'run' script will take +# over process ID 1. This is necessary so that the application will +# receive signals properly. + +echo " -----> Running builder run script ($S2I_SCRIPTS_PATH/run)" + +exec $S2I_SCRIPTS_PATH/run diff --git a/.s2i/environment b/.s2i/environment new file mode 100644 index 0000000..76be426 --- /dev/null +++ b/.s2i/environment @@ -0,0 +1,4 @@ +S2I_SCRIPTS_PATH=/usr/libexec/s2i +S2I_BASH_ENV=/opt/app-root/etc/scl_enable +DISABLE_COLLECTSTATIC=1 +DISABLE_MIGRATE=1 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..417440f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM centos/python-35-centos7:latest + +USER root + +COPY . /tmp/src + +RUN mv /tmp/src/.s2i/bin /tmp/scripts + +RUN rm -rf /tmp/src/.git* && \ + chown -R 1001 /tmp/src && \ + chgrp -R 0 /tmp/src && \ + chmod -R g+w /tmp/src + +USER 1001 + +ENV S2I_SCRIPTS_PATH=/usr/libexec/s2i \ + S2I_BASH_ENV=/opt/app-root/etc/scl_enable \ + DISABLE_COLLECTSTATIC=1 \ + DISABLE_MIGRATE=1 + +RUN /tmp/scripts/assemble + +CMD [ "/tmp/scripts/run" ] diff --git a/app.sh b/app.sh new file mode 100755 index 0000000..48a241f --- /dev/null +++ b/app.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +exec python manage.py runmodwsgi --log-to-terminal --port 8080 \ + --url-alias /media media diff --git a/blog/__init__.py b/blog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/admin.py b/blog/admin.py new file mode 100644 index 0000000..47f03fd --- /dev/null +++ b/blog/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Post + +admin.site.register(Post) diff --git a/blog/apps.py b/blog/apps.py new file mode 100644 index 0000000..7930587 --- /dev/null +++ b/blog/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class BlogConfig(AppConfig): + name = 'blog' diff --git a/blog/forms.py b/blog/forms.py new file mode 100644 index 0000000..5482b27 --- /dev/null +++ b/blog/forms.py @@ -0,0 +1,9 @@ +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text', 'image') diff --git a/blog/migrations/0001_initial.py b/blog/migrations/0001_initial.py new file mode 100644 index 0000000..3686ba4 --- /dev/null +++ b/blog/migrations/0001_initial.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.6 on 2017-03-15 03:24 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Post', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('text', models.TextField()), + ('image', models.ImageField(upload_to='images/', verbose_name='Image')), + ('created_date', models.DateTimeField(default=django.utils.timezone.now)), + ('published_date', models.DateTimeField(blank=True, null=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/blog/migrations/__init__.py b/blog/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/models.py b/blog/models.py new file mode 100644 index 0000000..e825ecb --- /dev/null +++ b/blog/models.py @@ -0,0 +1,20 @@ +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + image = models.ImageField("Image", blank=True, null=True, upload_to="images/") + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title diff --git a/blog/static/css/blog.css b/blog/static/css/blog.css new file mode 100644 index 0000000..e32a7d3 --- /dev/null +++ b/blog/static/css/blog.css @@ -0,0 +1,46 @@ +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} diff --git a/blog/templates/blog/base.html b/blog/templates/blog/base.html new file mode 100644 index 0000000..b2c574f --- /dev/null +++ b/blog/templates/blog/base.html @@ -0,0 +1,28 @@ +{% load staticfiles %} + + + OpenShift Blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + diff --git a/blog/templates/blog/login.html b/blog/templates/blog/login.html new file mode 100644 index 0000000..7b6c16c --- /dev/null +++ b/blog/templates/blog/login.html @@ -0,0 +1,12 @@ +{% extends 'blog/base.html' %} + +{% block title %}Login{% endblock %} + +{% block content %} +

Login

+
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/blog/templates/blog/post_detail.html b/blog/templates/blog/post_detail.html new file mode 100644 index 0000000..391fa4c --- /dev/null +++ b/blog/templates/blog/post_detail.html @@ -0,0 +1,19 @@ +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + {% if user.is_authenticated %} + + {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+ {% if post.image %} + + {% endif %} +
+{% endblock %} diff --git a/blog/templates/blog/post_edit.html b/blog/templates/blog/post_edit.html new file mode 100644 index 0000000..79ccb02 --- /dev/null +++ b/blog/templates/blog/post_edit.html @@ -0,0 +1,9 @@ +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+
{% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/blog/templates/blog/post_list.html b/blog/templates/blog/post_list.html new file mode 100644 index 0000000..33014d1 --- /dev/null +++ b/blog/templates/blog/post_list.html @@ -0,0 +1,13 @@ +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} diff --git a/blog/tests.py b/blog/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/blog/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/blog/urls.py b/blog/urls.py new file mode 100644 index 0000000..7382f36 --- /dev/null +++ b/blog/urls.py @@ -0,0 +1,12 @@ +from django.conf.urls import url +from django.contrib.auth import views as auth_views + +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^login/$', auth_views.login, {'template_name': 'blog/login.html'}, name='login'), + url(r'^post/(?P\d+)/$', views.post_detail, name='post_detail'), + url(r'^post/(?P\d+)/edit/$', views.post_edit, name='post_edit'), + url(r'^post/new/$', views.post_new, name='post_new'), +] diff --git a/blog/views.py b/blog/views.py new file mode 100644 index 0000000..ebc5288 --- /dev/null +++ b/blog/views.py @@ -0,0 +1,39 @@ +from django.shortcuts import render, get_object_or_404, redirect +from django.utils import timezone +from .models import Post +from .forms import PostForm + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) + +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) + +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST, request.FILES) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) + +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, request.FILES, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) diff --git a/katacoda/__init__.py b/katacoda/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/katacoda/settings.py b/katacoda/settings.py new file mode 100644 index 0000000..a9b854f --- /dev/null +++ b/katacoda/settings.py @@ -0,0 +1,152 @@ +""" +Django settings for katacoda project. + +Generated by 'django-admin startproject' using Django 1.10.6. + +For more information on this file, see +https://docs.djangoproject.com/en/1.10/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.10/ref/settings/ +""" + +import os + +# 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 +# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'w9mp-ntfm6b1k1!i3nx6kd)jehhnu=r)o)0d!s*rn&36dtquth' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'mod_wsgi.server', + 'blog', +] + +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 = 'katacoda.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 = 'katacoda.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.10/ref/settings/#databases + +import dj_database_url + +if os.environ.get('DATABASE_URL'): + DATABASES = { + 'default': dj_database_url.config(conn_max_age=600) + } + +else: + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } + + +# Password validation +# https://docs.djangoproject.com/en/1.10/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/1.10/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.10/howto/static-files/ + +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') + +MEDIA_URL = '/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['console'], + 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), + }, + }, +} + +LOGIN_REDIRECT_URL = 'post_list' diff --git a/katacoda/urls.py b/katacoda/urls.py new file mode 100644 index 0000000..7851e98 --- /dev/null +++ b/katacoda/urls.py @@ -0,0 +1,29 @@ +"""katacoda URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.10/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" + +from django.conf.urls import include, url +from django.contrib import admin +from django.conf.urls.static import static + +from . import settings + +urlpatterns = [ + url(r'^admin/', admin.site.urls), + url(r'', include('blog.urls')), +] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/katacoda/wsgi.py b/katacoda/wsgi.py new file mode 100644 index 0000000..30e4669 --- /dev/null +++ b/katacoda/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for katacoda 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/1.10/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "katacoda.settings") + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..f776eb5 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "katacoda.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/posts.json b/posts.json new file mode 100644 index 0000000..eeae82b --- /dev/null +++ b/posts.json @@ -0,0 +1 @@ +[{"model": "blog.post", "pk": 1, "fields": {"author": 1, "title": "What is OpenShift Origin?", "text": "Origin is the upstream community project that powers OpenShift. Built around a core of Docker container packaging and Kubernetes container cluster management, Origin is also augmented by application lifecycle management functionality and DevOps tooling. Origin provides a complete open source container application platform.", "created_date": "2017-03-14T03:26:20.023Z", "published_date": "2017-03-14T03:26:20.026Z"}}, {"model": "blog.post", "pk": 2, "fields": {"author": 1, "title": "What is Kubenetes?", "text": "Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.", "created_date": "2017-03-14T03:27:12.146Z", "published_date": "2017-03-14T03:27:12.149Z"}}] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f836030 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +django~=1.10.0 +dj_database_url +mod_wsgi +Pillow +psycopg2