--- /dev/null
+.eric6project/
+.ropeproject/
+.directory/
+.kdev4/
+*.pyc
+*.pyo
+*.orig
+*.bak
+*.rej
+*~
+cur/
+tmp/
+__pycache__/
+*.DS_Store
--- /dev/null
+from django.contrib import admin
+from core.models import StablePart, Bay, Horse, FodderPlan, Misc
+
+# Register your models here.
+admin.site.register(StablePart)
+admin.site.register(Bay)
+admin.site.register(Horse)
+admin.site.register(FodderPlan)
+admin.site.register(Misc)
--- /dev/null
+from django.apps import AppConfig
+
+
+class CoreConfig(AppConfig):
+ name = 'core'
--- /dev/null
+# Generated by Django 2.2 on 2019-04-06 22:06
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Bay',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('bay_number', models.IntegerField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='FodderPlan',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('fodder', models.TextField()),
+ ('valid_since', models.DateTimeField()),
+ ('valid_until', models.DateTimeField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Horse',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=180)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Misc',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('value', models.TextField()),
+ ('valid_since', models.DateTimeField()),
+ ('valid_until', models.DateTimeField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='StablePart',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=140)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='IsInBay',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('in_bay_since', models.DateField()),
+ ('in_bay_until', models.DateField()),
+ ('bay', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Bay')),
+ ('horse', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Horse')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='horse',
+ name='bay',
+ field=models.ManyToManyField(blank=True, null=True, through='core.IsInBay', to='core.Bay'),
+ ),
+ migrations.AddField(
+ model_name='horse',
+ name='fodder',
+ field=models.ManyToManyField(blank=True, null=True, to='core.FodderPlan'),
+ ),
+ migrations.AddField(
+ model_name='horse',
+ name='misc_remarks',
+ field=models.ManyToManyField(blank=True, null=True, to='core.Misc'),
+ ),
+ migrations.AddField(
+ model_name='bay',
+ name='located_in',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.StablePart'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2 on 2019-04-07 20:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='horse',
+ name='colour',
+ field=models.CharField(blank=True, max_length=120, null=True),
+ ),
+ migrations.AddField(
+ model_name='horse',
+ name='markings',
+ field=models.CharField(blank=True, max_length=120, null=True),
+ ),
+ migrations.AlterField(
+ model_name='horse',
+ name='bay',
+ field=models.ManyToManyField(blank=True, through='core.IsInBay', to='core.Bay'),
+ ),
+ migrations.AlterField(
+ model_name='horse',
+ name='fodder',
+ field=models.ManyToManyField(blank=True, to='core.FodderPlan'),
+ ),
+ migrations.AlterField(
+ model_name='horse',
+ name='misc_remarks',
+ field=models.ManyToManyField(blank=True, to='core.Misc'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2 on 2019-04-07 20:56
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0002_auto_20190407_2011'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='bay',
+ name='name',
+ field=models.CharField(blank=True, max_length=120, null=True),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2 on 2019-04-09 22:42
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0003_bay_name'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='bay',
+ name='located_in',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bays', to='core.StablePart'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2 on 2019-04-09 22:56
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0004_auto_20190409_2242'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='horse',
+ name='bay',
+ field=models.ManyToManyField(blank=True, related_name='in_bay', through='core.IsInBay', to='core.Bay'),
+ ),
+ ]
--- /dev/null
+# Generated by Django 2.2 on 2019-04-09 22:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0005_auto_20190409_2256'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='horse',
+ name='bay',
+ field=models.ManyToManyField(blank=True, related_name='horses', through='core.IsInBay', to='core.Bay'),
+ ),
+ ]
--- /dev/null
+from django.db import models
+
+# Create your models here.
+
+
+class StablePart(models.Model):
+ name = models.CharField(max_length=140)
+
+ def __str__(self):
+ return 'Stable Part ' + self.name
+
+
+class Bay(models.Model):
+ name = models.CharField(max_length=120, null=True, blank=True)
+ bay_number = models.IntegerField()
+ located_in = models.ForeignKey(StablePart, on_delete=models.CASCADE, related_name='bays')
+
+ def __str__(self):
+ return (self.name if self.name is not None else '')\
+ + '(number ' + str(self.bay_number) + ')'
+
+
+class FodderPlan(models.Model):
+ fodder = models.TextField()
+ valid_since = models.DateTimeField()
+ valid_until = models.DateTimeField()
+
+ def __str__(self):
+ return self.valid_since + ' - ' + self.valid_until
+
+
+class Misc(models.Model):
+ value = models.TextField()
+ valid_since = models.DateTimeField()
+ valid_until = models.DateTimeField()
+
+
+class Horse(models.Model):
+ name = models.CharField(max_length=180)
+ colour = models.CharField(max_length=120, null=True, blank=True)
+ markings = models.CharField(max_length=120, null=True, blank=True)
+ bay = models.ManyToManyField(Bay, through='IsInBay', blank=True, related_name='horses')
+ fodder = models.ManyToManyField(FodderPlan, blank=True)
+ misc_remarks = models.ManyToManyField(Misc, blank=True)
+
+ def __str__(self):
+ return self.name
+
+
+class IsInBay(models.Model):
+ horse = models.ForeignKey(Horse, on_delete=models.CASCADE)
+ bay = models.ForeignKey(Bay, on_delete=models.CASCADE)
+ in_bay_since = models.DateField()
+ in_bay_until = models.DateField()
--- /dev/null
+{% extends 'base.html' %}
+
+{% block title %}Bay {{ object }} - {{ block.super }}{% endblock %}
+
+{% block main %}
+<div class="card">
+ <h3>{{ object }}</h3>
+ <div>
+ <ul>
+ {% for inbay in object.isinbay_set.all %}
+ <li><a href="/horse/{{ inbay.horse.id }}">{{ inbay.in_bay_since }} bis {{ inbay.in_bay_until }}: {{ inbay.horse }}</a></li>
+ {% empty %}
+ <li>EMPTY</li>
+ {% endfor %}
+ </ul>
+ </div>
+</div>
+{% endblock %}
--- /dev/null
+{% extends 'base.html' %}
+
+{% block title %}{{ object.name }} - {{ block.super }}{% endblock %}
+
+{% block main %}
+<div class="card">
+ <h3>{{ object.name }}</h3>
+ <div>
+ <ul>
+ {% for bay in object.bays.all %}
+ <li><a href="/bay/{{ bay.id }}">{{ bay }}</a></li>
+ {% empty %}
+ <li>EMPTY</li>
+ {% endfor %}
+ </ul>
+ </div>
+</div>
+{% endblock %}
--- /dev/null
+{% extends 'base.html' %}
+
+{% block title %}Stable Parts - {{ block.super }}{% endblock %}
+
+{% block main %}
+ <ul>
+ {% for sp in object_list %}
+ <li><a href="/stablepart/{{sp.id}}">{{ sp }}</a></li>
+ {% empty %}
+ <li>No Stable yet</li>
+ {% endfor %}
+ </ul>
+{% endblock %}
+
--- /dev/null
+from django.test import TestCase
+
+# Create your tests here.
--- /dev/null
+from django.urls import path
+
+from . import views
+
+app_name = 'core'
+urlpatterns = [
+ path('stableparts', views.StableParts.as_view(), name='StableParts'),
+ path('stablepart/<int:pk>', views.StablePartDetail.as_view(), name='StablePartDetail'),
+ path('bay/<int:pk>', views.BayDetail.as_view(), name='BayDetail'),
+]
--- /dev/null
+from django.shortcuts import render
+from django.views.generic import ListView, DetailView
+from core.models import StablePart, Bay
+
+# Create your views here.
+
+
+class StableParts(ListView):
+ model = StablePart
+
+
+class StablePartDetail(DetailView):
+ model = StablePart
+
+
+class BayDetail(DetailView):
+ model = Bay
--- /dev/null
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stable.settings')
+ try:
+ from django.core.management import execute_from_command_line
+ except ImportError as exc:
+ 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?"
+ ) from exc
+ execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+ main()
--- /dev/null
+[Project]
+CreatedFrom=
+Manager=KDevCustomBuildSystem
+Name=stable
--- /dev/null
+"""
+Django settings for stable project.
+
+Generated by 'django-admin startproject' using Django 2.2.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/2.2/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/2.2/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/2.2/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'on!o2^64g5lf(*avme1dbcz2y*kkv@#$rhk=gmo_%i#)c&-l)j'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+ 'core',
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+]
+
+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 = 'stable.urls'
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
+ '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',
+ ],
+ 'string_if_invalid': 'INVALID_VALUE',
+ },
+ },
+]
+
+WSGI_APPLICATION = 'stable.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'NAME': 'stable',
+ 'USER': 'stable',
+ 'PASSWORD': 'po1Ahf5eph7dogh1',
+ }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/2.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/2.2/topics/i18n/
+
+LANGUAGE_CODE = 'en-gb'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/2.2/howto/static-files/
+
+STATIC_URL = '/static/'
+STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
--- /dev/null
+"""stable URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+ https://docs.djangoproject.com/en/2.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 path, include
+import core.urls
+
+urlpatterns = [
+ path('admin/', admin.site.urls),
+ path('', include(core.urls, namespace='core')),
+]
--- /dev/null
+"""
+WSGI config for stable 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/2.2/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stable.settings')
+
+application = get_wsgi_application()
--- /dev/null
+* {
+ box-sizing: border-box;
+}
+
+html {
+ height: 100%;
+}
+
+body {
+ display: grid;
+ grid-template-columns: 15em 1fr;
+ grid-template-rows: 1fr 6fr 1fr;
+ grid-template-areas:
+ "header header"
+ "nav main"
+ "footer footer";
+ margin: 0;
+ height: 100%;
+}
+
+div#header {
+ grid-area: header;
+ border: 1px solid red;
+}
+
+div#nav {
+ grid-area: nav;
+ border: 1px solid red;
+}
+
+div#main {
+ grid-area: main;
+ border: 1px solid red;
+}
+
+div#footer {
+ grid-area: footer
+ border: 1px solid red;
+}
+
+div.card {
+ box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
+ transition: 0.3s;
+ border-radius: 5px;
+}
+
+div.card:hover {
+ box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
+}
+
+div.card > img {
+ border-radius: 5px 5px 0 0;
+}
+
+div.card > h1,h2,h3,h4,div {
+ padding: 5px;
+}
+
+div.card > h1,h2,h3,h4 {
+ margin: 0;
+ border-bottom: 1px solid lightgrey;
+}
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
+ {% load static %}
+ <link rel="stylesheet" type="text/css" href="{% static 'base.css' %}" />
+ <title>{% block title %} Stable Management {% endblock %}</title>
+ </head>
+ <body>
+ <div id="header">{% block header %}<div class="card"><h1>Stable Management</h1><div>content</div></div>{% endblock %}</div>
+ <div id="nav">{% block nav %}nav{% endblock %}</div>
+ <div id="main">{% block main %}{% endblock %}</div>
+ <div id="footer">{%block footer %}footer{% endblock %}</div>
+ </body>
+</html>