Restructured everything.

This commit is contained in:
2019-10-08 14:50:10 +02:00
parent 5336de4959
commit 587c2849b6
46 changed files with 102 additions and 328 deletions

0
apps/base/__init__.py Normal file
View File

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,331 @@
/*!
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
text-align: left;
background-color: #fff;
}
[tabindex="-1"]:focus {
outline: 0 !important;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
border-bottom: 0;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: .5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -.25em;
}
sup {
top: -.5em;
}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
a:not([href]):not([tabindex]) {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):focus {
outline: 0;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
}
pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
}
figure {
margin: 0 0 1rem;
}
img {
vertical-align: middle;
border-style: none;
}
svg {
overflow: hidden;
vertical-align: middle;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: #6c757d;
text-align: left;
caption-side: bottom;
}
th {
text-align: inherit;
}
label {
display: inline-block;
margin-bottom: 0.5rem;
}
button {
border-radius: 0;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
select {
word-wrap: normal;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button:not(:disabled),
[type="button"]:not(:disabled),
[type="reset"]:not(:disabled),
[type="submit"]:not(:disabled) {
cursor: pointer;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
-webkit-appearance: listbox;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
padding: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
line-height: inherit;
color: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
cursor: pointer;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
#page-header {
padding-left: 1rem;
border-bottom-style: solid;
border-bottom-width: 2px;
border-bottom-color: #000;
margin-bottom: 1rem;
}
#page-footer {
padding-right: 1rem;
}
#page-footer > div.signum {
float: right;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
<!DOCTYPE html>
{% load static %}
<html lang="{{ LANGUAGE_CODE|default:'de' }}">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link type="text/css" href="{% static 'base/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet" />
<link type="text/css" href="{% static 'base/css/local.css' %}" rel="stylesheet" />
<script type="text/javascript" src="{% static 'base/js/jquery.min.js' %}"></script>
<script type="text/javascript" src="{% static 'base/bootstrap/js/bootstrap.min.js' %}"></script>
<title>django-test</title>
</head>
<body>
<div id="page">
<div id="page-header">
<h1>
<a href="{% url 'root' %}">django-test</a>
</h1>
</div>
<div id="page-body">
{% block page-body %}{% endblock %}
</div>
<div id="page-footer">
<div class="signum">{% block signum %}{% include 'signum.html' %}{% endblock %}</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,27 @@
{% extends "base/base.html" %}
{% block page-body %}
<div class="container">
<div class="jumbotron">
<h1>Hello,</h1>
<p>
my name is {{ hostname|capfirst }} and I am your server right now.
</p>
<p>
Did I say now?<br />
My clock says {{ time|time:'TIME_FORMAT'|default:'nothing' }},
{% if time %}
and we are talking about the {{ time|time:'e' }} timezone.
{% else %}
and this is no good.
{% endif %}
</p>
<p>
{% with color_hex=color_hex|default:'47825b' %}
By the way, this is my favorite color:
<span class="badge" style="background-color: #{{ color_hex }};">&nbsp; #{{ color_hex }} &nbsp;</span>
{% endwith %}
</p>
</div>
</div>
{% endblock page-body %}

View File

@@ -0,0 +1 @@
<a href="mailto:heinzel@heinzelwelt.de">heinzel@heinzelwelt.de</a>

View File

View File

@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.conf import settings
from django.template.context import Context
from django.test import SimpleTestCase
class BaseTemplateTestCase(SimpleTestCase):
def assertInHTML_multi(self, response, needles, format_kwargs=None):
content = response.content.decode('utf-8')
for needle in needles:
if format_kwargs is not None:
needle = needle.format(**format_kwargs)
self.assertInHTML(needle, content)
def setUp(self):
super(BaseTemplateTestCase, self).setUp()
self.response = self.client.get('/')
self.static_url = settings.STATIC_URL
self.base_prefix = 'base/'
def test_template_usage(self):
response = self.response
self.assertTemplateUsed(response, 'base/base.html')
def test_local_css_link(self):
response = self.response
format_kwargs = {
'static_url': self.static_url,
'base_prefix': self.base_prefix,
}
needles = (
'<link type="text/css" href="{static_url}{base_prefix}css/local.css" rel="stylesheet" />',
)
self.assertInHTML_multi(response, needles, format_kwargs)
def test_bootstrap_css_links(self):
response = self.response
format_kwargs = {
'static_url': self.static_url,
'base_prefix': self.base_prefix,
}
needles = (
# bootstrap css
'<link type="text/css" href="{static_url}{base_prefix}bootstrap/css/bootstrap.min.css"'
' rel="stylesheet" />',
# jquery.js file
'<script type="text/javascript" src="{static_url}{base_prefix}js/jquery.min.js"></script>',
# bootstrap js file
'<script type="text/javascript" src="{static_url}{base_prefix}bootstrap/js/bootstrap.min.js"></script>',
)
self.assertInHTML_multi(response, needles, format_kwargs)
def test_page_footer(self):
response = self.response
self.assertTemplateUsed(response, 'signum.html')
for template in response.templates:
if template.name == 'signum.html':
signum = template.render(Context({}))
break
else: # pragma: no cover
self.fail('Cannot find signum template.')
needle = """
<div id="page-footer">
<div class="signum">{signum}</div>
</div>
""".format(signum=signum)
self.assertInHTML(needle, response.content.decode('utf-8'))

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import socket
from django.test import SimpleTestCase
class DjangoAdminTestCase(SimpleTestCase):
def test_djangoadmin(self):
response = self.client.get('/djangoadmin', follow=True)
self.assertContains(response, 'Django administration')
class RootTestCase(SimpleTestCase):
def setUp(self):
super(RootTestCase, self).setUp()
self.response = self.client.get('/')
def test_root_template(self):
response = self.response
self.assertTemplateUsed(response, 'base/root.html')
def test_root_context(self):
response = self.response
self.assertIn('hostname', response.context)
hostname = socket.gethostname()
self.assertEqual(response.context['hostname'], hostname)
def test_root_content(self):
response = self.response
hostname = socket.gethostname().capitalize()
self.assertContains(response, hostname)

12
apps/base/tests/utils.py Normal file
View File

@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
from tempfile import mkdtemp as _mkdtmp
def mkdtemp(prefix):
dirname = os.path.dirname
pkg_base_dir = dirname(dirname(dirname(__file__)))
tmp_dir = os.path.join(pkg_base_dir, 'tmp')
os.makedirs(tmp_dir, exist_ok=True)
return _mkdtmp(prefix=prefix, dir=tmp_dir)

11
apps/base/urls.py Normal file
View File

@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('', views.RootView.as_view(), name='root'),
path('djangoadmin/', admin.site.urls),
]

23
apps/base/views.py Normal file
View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import re
import socket
from django.utils import timezone
from django.views import generic
class RootView(generic.TemplateView):
template_name = 'base/root.html'
def get_context_data(self, **kwargs):
if 'hostname' not in kwargs:
kwargs['hostname'] = socket.gethostname()
if 'color_hex' not in kwargs:
buf = kwargs['hostname']
buf = re.sub('[-.]', '', buf)
buf = buf[:6].lower()
if re.match('[0-9a-f]{6}', buf):
kwargs['color_hex'] = buf
if 'time' not in kwargs:
kwargs['time'] = timezone.now()
return super(RootView, self).get_context_data(**kwargs)