Compare commits
48
Commits
iss01
...
ai-optimisation
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3322649f05 | ||
|
|
6b99dd5250 | ||
|
|
d4dbd3d9da | ||
|
|
5b7f847bc6 | ||
|
|
99eaafff00 | ||
|
|
446a55f3e5 | ||
|
|
2f970d6eb4 | ||
|
|
c1deabc692 | ||
|
|
fb3e425471 | ||
|
|
46bc47f046 | ||
|
|
8db2774f7c | ||
|
|
272498b4ce | ||
|
|
12323615c7 | ||
|
|
9d6857cfe2 | ||
|
|
565bb3963e | ||
|
|
3b2deb865e | ||
|
|
a221c0e37d | ||
|
|
de3e844089 | ||
|
|
72be0aebdb | ||
|
|
929b540753 | ||
|
|
b44d31d128 | ||
|
|
26833e389a | ||
|
|
ffed1ef6e8 | ||
|
|
db5ece431b | ||
|
|
20ef745b3f | ||
|
|
45293586a7 | ||
|
|
8f9398ced5 | ||
|
|
589884c4be | ||
|
|
5c3c56ecc3 | ||
|
|
6042838f28 | ||
|
|
c2eede9500 | ||
|
|
e3ef06a41a | ||
|
|
9be82123da | ||
|
|
911b19068c | ||
|
|
c02f137c0b | ||
|
|
538f6262fd | ||
|
|
4b2f7e4641 | ||
|
|
d99eee4751 | ||
|
|
5a0a1daa39 | ||
|
|
20f0a836e5 | ||
|
|
c0eb583a69 | ||
|
|
7292957497 | ||
|
|
62ec42297d | ||
|
|
5b033803a8 | ||
|
|
364166d84b | ||
|
|
de904d4ad4 | ||
|
|
7c66399c8f | ||
|
|
ae3d3d2c12 |
+45
-8
@@ -1,9 +1,46 @@
|
|||||||
*.pyc
|
# Virtuelle Umgebung
|
||||||
*.swp
|
venv/
|
||||||
bin/
|
env/
|
||||||
manage.py
|
ENV/
|
||||||
|
.venv
|
||||||
|
|
||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# Django
|
||||||
|
*.log
|
||||||
|
db.sqlite3
|
||||||
media/
|
media/
|
||||||
old_stuff/
|
staticfiles/
|
||||||
static/
|
|
||||||
templates/blogindex.html-media
|
# IDE
|
||||||
tippy/static/
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Umgebungsvariablen
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
- getSeason() only for staff members
|
||||||
|
- new view staff()
|
||||||
|
- updated bootstrap to version 3.4.1
|
||||||
|
- updated jquery to 3.6.3
|
||||||
|
- changed container layout in main view 'matchday'
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for TipPy 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.0/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'TipPy.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
"""
|
||||||
|
Django settings for TipPy project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 4.0.6.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.0/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/4.0/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.0/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-jiw8js(^@d)no7tv(oq+ugl3kj=f8@j-kz3bj530&!%!$cjqj9'
|
||||||
|
|
||||||
|
# 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',
|
||||||
|
'django.contrib.humanize',
|
||||||
|
'tipp'
|
||||||
|
]
|
||||||
|
|
||||||
|
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 = 'TipPy.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [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',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'TipPy.wsgi.application'
|
||||||
|
WSGI_APPLICATION = 'TipPy.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
|
'NAME': 'tippy',
|
||||||
|
'USER': 'tippy',
|
||||||
|
'PASSWORD': 'tippy',
|
||||||
|
'HOST': 'localhost',
|
||||||
|
'PORT': '5432',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.0/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.0/topics/i18n/
|
||||||
|
LANGUAGE_CODE = 'de-de'
|
||||||
|
TIME_ZONE = 'Europe/Berlin'
|
||||||
|
USE_I18N = True
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
||||||
|
# Example: "/home/media/media.lawrence.com/media/"
|
||||||
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
|
||||||
|
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||||
|
# trailing slash.
|
||||||
|
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
# Absolute path to the directory static files should be collected to.
|
||||||
|
# Don't put anything in this directory yourself; store your static files
|
||||||
|
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
|
||||||
|
# Example: "/home/media/media.lawrence.com/static/"
|
||||||
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
|
||||||
|
|
||||||
|
if not DEBUG:
|
||||||
|
STATIC_ROOT = ''
|
||||||
|
|
||||||
|
STATICFILES_DIRS = [
|
||||||
|
#os.path.join(BASE_DIR, 'static/'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# STATIC_ROOT=os.path.join(BASE_DIR,"static/")
|
||||||
|
# STATIC_URL = 'static/'
|
||||||
|
# STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
# Redirect on logout
|
||||||
|
LOGOUT_REDIRECT_URL = "home"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from django.contrib import admin, auth
|
||||||
|
from django.urls import include, path, re_path
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', include('tipp.urls')),
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
]
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for TipPy 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.0/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'TipPy.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "TipPy.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()
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
asgiref==3.12.1
|
||||||
|
Django==6.1.1
|
||||||
|
pillow==12.3.0
|
||||||
|
psycopg2==2.9.13
|
||||||
|
pytz==2026.3.post1
|
||||||
|
sqlparse==0.6.0
|
||||||
|
suds-community==1.2.0
|
||||||
|
urllib3==2.8.0
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n static %}
|
||||||
|
{% load humanize %}
|
||||||
|
{% block head %}
|
||||||
|
<script type="text/javascript" src="{% static 'javascript/tippy.js' %}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block nav %}
|
||||||
|
{% include "nav.html" with ls=ls season=season %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div id="content-main">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-7">
|
||||||
|
<h2>Über TipPy</h2>
|
||||||
|
<p>TipPy ist eine responsive Web-Applikation für Tippspiele mit
|
||||||
|
einem "Mobile-First-Ansatz" . Unterstützt werden alle auf
|
||||||
|
<a href="http://www.OpenLigaDB.de">OpenLigaDB</a> bereitgestellten
|
||||||
|
Sportarten und Ligen.
|
||||||
|
|
||||||
|
TipPy wurde in <a href="http://www.python.org">Python</a> umgesetzt
|
||||||
|
und benutzt die Frameworks <a href="http://www.django.org">Django</a>
|
||||||
|
als Web Application Framework, und Twitters <a href="www.getbootstrap.com">
|
||||||
|
Bootstrap</a> für CSS.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
+12
-7
@@ -16,13 +16,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
<link href="{{ STATIC_URL }}css/bootstrap.min.css" rel="stylesheet">
|
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
||||||
|
|
||||||
<!-- Bootstrap-Theme -->
|
<!-- Bootstrap-Theme -->
|
||||||
<link href="{{ STATIC_URL }}css/bootstrap-theme.min.css" rel="stylesheet">
|
<link href="{% static 'css/bootstrap-theme.min.css' %}" rel="stylesheet">
|
||||||
|
|
||||||
<!-- Bootstrap-Theme -->
|
<!-- Bootstrap-Theme -->
|
||||||
<link href="{{ STATIC_URL }}css/tippy-bootstrap.css" rel="stylesheet">
|
<link href="{% static 'css/tippy-bootstrap.css' %}" rel="stylesheet">
|
||||||
|
|
||||||
<!-- Unterstützung für Media Queries und HTML5-Elemente im Internet Explorer über HTML5 shim und Respond.js -->
|
<!-- Unterstützung für Media Queries und HTML5-Elemente im Internet Explorer über HTML5 shim und Respond.js -->
|
||||||
<!-- ACHTUNG: Respond.js funktioniert nicht, wenn du die Seite über file:// aufrufst -->
|
<!-- ACHTUNG: Respond.js funktioniert nicht, wenn du die Seite über file:// aufrufst -->
|
||||||
@@ -36,9 +36,9 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- jQuery (wird für Bootstrap JavaScript-Plugins benötigt) -->
|
<!-- jQuery (wird für Bootstrap JavaScript-Plugins benötigt) -->
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
|
||||||
<!-- Binde alle kompilierten Plugins zusammen ein (wie hier unten) oder such dir einzelne Dateien nach Bedarf aus -->
|
<!-- Binde alle kompilierten Plugins zusammen ein (wie hier unten) oder such dir einzelne Dateien nach Bedarf aus -->
|
||||||
<script src="{{ STATIC_URL }}js/bootstrap.min.js"></script>
|
<script src="{% static 'js/bootstrap.min.js'%}"></script>
|
||||||
|
|
||||||
{% block nav %}{% endblock %}
|
{% block nav %}{% endblock %}
|
||||||
|
|
||||||
@@ -51,8 +51,13 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<p>© Martin Bley, 2014-2015 | Dank an <a href="http://openligadb.de">OpenLigaDB</a> für
|
<p>
|
||||||
die Bereitstellung der Spielergebnisse.</p>
|
<div class="pull-left">
|
||||||
|
© Martin Bley, 2014-2023 | Dank an
|
||||||
|
<a href="http://openligadb.de">OpenLigaDB</a> für die Bereitstellung der
|
||||||
|
Spielergebnisse.
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+61
-58
@@ -2,71 +2,74 @@
|
|||||||
{% load i18n static %}
|
{% load i18n static %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<title> TipPy Blog</title>
|
<title> TipPy Blog</title>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block nav %}
|
{% block nav %}
|
||||||
{% include "nav.html" with ls=ls season=season %}
|
{% include "nav.html" with ls=ls season=season %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div id="content-main">
|
<div id="content-main">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<h2>TipPy Blog</h2>
|
<h2>TipPy Blog</h2>
|
||||||
<p class="text-right">
|
<p class="text-right">
|
||||||
<a class="btn btn-default" href="/blog/newpost" role="button">Neue Nachricht</a>
|
<a class="btn btn-default" href="/blog/newpost" role="button">Neue Nachricht</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% for post, avatar in posts %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-7">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">
|
|
||||||
{{post.author.first_name}} schrieb {{post.created|naturaltime}},
|
|
||||||
<a href="{{post.get_absolute_url}}">{{post.title}}</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<ul class="media-list">
|
||||||
{% if avatar %}
|
{% for post, avatar in posts %}
|
||||||
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic" src="/media/{{avatar}}" />
|
<li class="media">
|
||||||
{% else %}
|
<a href="#" class="pull-left">
|
||||||
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic" src="/media/profiles/dummy.png" />
|
{% if avatar %}
|
||||||
{% endif %}
|
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic"
|
||||||
{{post.content|safe}}
|
src="/media/{{ avatar }}"/>
|
||||||
</div>
|
{% else %}
|
||||||
</div>
|
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic"
|
||||||
</div>
|
src="/media/profiles/dummy.png"/>
|
||||||
</div>
|
{% endif %}
|
||||||
{% endfor %}
|
</a>
|
||||||
<div class="row">
|
<div class="media-body">
|
||||||
<div class="col-md-7">
|
<span class="text-muted pull-right">
|
||||||
<nav>
|
<small class="text-muted">{{ post.created|naturaltime }}</small>
|
||||||
<ul class="pager">
|
</span>
|
||||||
{% if posts.has_previous %}
|
<strong class="text-success">{{ post.author.first_name }}</strong>
|
||||||
<li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous">
|
<p>{{ post.content|safe }}</p>
|
||||||
<a href="/blog/{{ page|add:"-1" }}">
|
</div>
|
||||||
{% else %}
|
</li>
|
||||||
<li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous inactive">
|
{% endfor %}
|
||||||
<a href="/blog/{{ page }}">
|
|
||||||
{% endif %}
|
|
||||||
<span aria-hidden="true">←</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
Seite {{ posts.number }} von {{ posts.paginator.num_pages }}.
|
|
||||||
{% if posts.has_next %}
|
|
||||||
<li data-toggle="tooltip" title="{% trans 'next' %}" class="next">
|
|
||||||
<a href="/blog/{{ page|add:"1" }}">
|
|
||||||
{% else %}
|
|
||||||
<li data-toggle="tooltip" title="{% trans 'next' %}" class="next inactive">
|
|
||||||
<a href="/blog/{{ page }}">
|
|
||||||
{% endif %}
|
|
||||||
<span aria-hidden="true">→</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-7">
|
||||||
|
<nav>
|
||||||
|
<ul class="pager">
|
||||||
|
{% if posts.has_previous %}
|
||||||
|
<li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous">
|
||||||
|
<a href="/blog/{{ page|add:"-1" }}">
|
||||||
|
{% else %}
|
||||||
|
<li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous inactive">
|
||||||
|
<a href="/blog/{{ page }}">
|
||||||
|
{% endif %}
|
||||||
|
<span aria-hidden="true">←</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
Seite {{ posts.number }} von {{ posts.paginator.num_pages }}.
|
||||||
|
{% if posts.has_next %}
|
||||||
|
<li data-toggle="tooltip" title="{% trans 'next' %}" class="next">
|
||||||
|
<a href="/blog/{{ page|add:"1" }}">
|
||||||
|
{% else %}
|
||||||
|
<li data-toggle="tooltip" title="{% trans 'next' %}" class="next inactive">
|
||||||
|
<a href="/blog/{{ page }}">
|
||||||
|
{% endif %}
|
||||||
|
<span aria-hidden="true">→</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{% load humanize %}
|
||||||
|
<hr>
|
||||||
|
<p class="text-left">
|
||||||
|
<a class="btn btn-default" href="/blog/newpost" role="button">neuer Post</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="media-list">
|
||||||
|
{% for post, avatar in posts %}
|
||||||
|
<li class="media">
|
||||||
|
<a href="#" class="pull-left">
|
||||||
|
{% if avatar %}
|
||||||
|
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic"
|
||||||
|
src="/media/{{ avatar }}"/>
|
||||||
|
{% else %}
|
||||||
|
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic"
|
||||||
|
src="/media/profiles/dummy.png"/>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
<div class="media-body">
|
||||||
|
<span class="text-muted pull-right">
|
||||||
|
<small class="text-muted">{{ post.created|naturaltime }}</small>
|
||||||
|
</span>
|
||||||
|
<strong class="text-success">{{ post.author.first_name }}</strong>
|
||||||
|
<p>{{ post.content|safe }}</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load url from future %}
|
|
||||||
{% comment %}
|
|
||||||
Main page to authenticate users.
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
{% block head %}
|
|
||||||
<title>TipPy | Login</title>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block nav %}
|
|
||||||
{% include "nav_login.html" with ls=ls season=season %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
{% if form.errors %}
|
|
||||||
<div class="row">
|
|
||||||
<p>Benutzename und Passwort passen nicht zusammen. Bitte versuche es noch einmal.</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<form class="form-signin" role="form" method="post" action="{% url 'django.contrib.auth.views.login' %}">
|
|
||||||
<h2 class="form-signin-heading">Bitte melde dich an</h2>
|
|
||||||
{% csrf_token %}
|
|
||||||
<input class="form-control" type="text" autofocus="" required="" name="{{form.username.html_name}}" placeholder="Anmeldename" />
|
|
||||||
<input class="form-control" type="password" required="" placeholder="Passwort" name="{{form.password.html_name}}" />
|
|
||||||
<button class="btn btn-lg btn-primary btn-block" type="submit">Anmelden</button>
|
|
||||||
<input type="hidden" name="next" value="{{ next }}" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
+102
-96
@@ -2,108 +2,114 @@
|
|||||||
{% load i18n static %}
|
{% load i18n static %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<script type="text/javascript" src="{{ STATIC_URL }}javascript/tippy.js"></script>
|
<script type="text/javascript" src="{% static 'javascript/tippy.js' %}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block nav %}
|
{% block nav %}
|
||||||
{% include "nav.html" with ls=ls season=season %}
|
{% include "nav.html" with ls=ls season=season %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div id="content-main">
|
<div id="content-main">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-7">
|
<div class="col-md-6">
|
||||||
<h2>Neueste Nachrichten</h2>
|
<h3>Deine Tipps</h3>
|
||||||
<p class="text-right">
|
<nav>
|
||||||
<a class="btn btn-default" href="/blog/1" role="button">zum Blog</a>
|
<ul class="pager">
|
||||||
</p>
|
<li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous"><a
|
||||||
{% for post, avatar in posts %}
|
href="/matchday/{{ ls }}/{{ season }}/{{ cur_md|add:"-1"|stringformat:"02i" }}"><span
|
||||||
<div class="panel panel-default">
|
aria-hidden="true">←</span></a></li>
|
||||||
<div class="panel-heading">
|
{{ md_name }}
|
||||||
{{post.author.first_name}} schrieb {{post.created|naturaltime}},
|
<li data-toggle="tooltip" title="{% trans 'next' %}" class="next"><a
|
||||||
<a href="{{post.get_absolute_url}}">{{post.title}}</a>
|
href="/matchday/{{ ls }}/{{ season }}/{{ cur_md|add:"1"|stringformat:"02i" }}"><span
|
||||||
|
aria-hidden="true">→</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<form role="form" action="" method="post">{% csrf_token %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-condensed">
|
||||||
|
<tr>
|
||||||
|
<th>Anstoß</th>
|
||||||
|
<th>Heim</th>
|
||||||
|
<th>Gast</th>
|
||||||
|
<th>Erg.</th>
|
||||||
|
<th colspan="2">Tipp</th>
|
||||||
|
</tr>
|
||||||
|
{% for match in matches %}
|
||||||
|
{% if match.started and not match.finished %}
|
||||||
|
<tr class="danger">{% else %}
|
||||||
|
<tr>{% endif %}
|
||||||
|
<td>{{ match.matchDateTime }}</td>
|
||||||
|
{% if match.iconURLTeam1 != "" %}
|
||||||
|
<td><img src="{{ match.iconURLTeam1 }}" width="20"/>
|
||||||
|
{% else %}
|
||||||
|
<td><img src="{{ STATIC_URL }}{{ match.iconTeam1 }}"/>
|
||||||
|
{% endif %}
|
||||||
|
<span class="hidden-xs"> {{ match.nameTeam1 }}</span>
|
||||||
|
<span class="visible-xs"> {{ match.abbrTeam1 }}</span>
|
||||||
|
</td>
|
||||||
|
{% if match.iconURLTeam1 != "" %}
|
||||||
|
<td><img src="{{ match.iconURLTeam2 }}" width="20"/>
|
||||||
|
{% else %}
|
||||||
|
<td><img src="{{ STATIC_URL }}{{ match.iconTeam2 }}"/>
|
||||||
|
{% endif %}
|
||||||
|
<span class="hidden-xs"> {{ match.nameTeam2 }}</span>
|
||||||
|
<span class="visible-xs"> {{ match.abbrTeam2 }}</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ match.matchResult }}</td>
|
||||||
|
<td>{{ match.tippFormTeam1 }}</td>
|
||||||
|
<td>{{ match.tippFormTeam2 }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-default btn-lg btn-block">
|
||||||
|
<span class="glyphicon glyphicon-saved" aria-hidden="true"></span> Tipps abgeben
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% for mandant, list in mandant_dict.items %}
|
||||||
|
<h3>Mitspieler {{ mandant }}</h3>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-condensed">
|
||||||
|
<tr>
|
||||||
|
<th>Tipper</th>
|
||||||
|
<th>Gesamt</th>
|
||||||
|
{% for match in matches %}
|
||||||
|
<th>
|
||||||
|
{% if match.iconURLTeam1 != "" %}
|
||||||
|
<img src="{{ match.iconURLTeam1 }}" width="20"/>
|
||||||
|
{% else %}
|
||||||
|
<img src="{{ STATIC_URL }}{{ match.iconTeam1 }}"/>
|
||||||
|
{% endif %}
|
||||||
|
<br/><br/>
|
||||||
|
{% if match.iconURLTeam2 != "" %}
|
||||||
|
<img src="{{ match.iconURLTeam2 }}" width="20"/>
|
||||||
|
{% else %}
|
||||||
|
<img src="{{ STATIC_URL }}{{ match.iconTeam2 }}"/>
|
||||||
|
{% endif %}
|
||||||
|
</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% for mate in list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ mate.mate.first_name }}</td>
|
||||||
|
<td>{{ mate.sum_score }}</td>
|
||||||
|
{% for tipp in mate.tipps %}
|
||||||
|
<td>{{ tipp }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h3>Chat</h3>
|
||||||
|
{% block chat %}
|
||||||
|
{% include "chat.xhtml" with posts=posts %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
|
||||||
{% if avatar %}
|
|
||||||
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic" src="/media/{{avatar}}" />
|
|
||||||
{% else %}
|
|
||||||
<img class="img-circle img-responsive pull-left blog" alt="Profile Pic" src="/media/profiles/dummy.png" />
|
|
||||||
{% endif %}
|
|
||||||
{{post.content|safe}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-7">
|
|
||||||
<h2>Deine Tipps</h2>
|
|
||||||
<nav>
|
|
||||||
<ul class="pager">
|
|
||||||
<li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous"><a href="/matchday/{{ ls }}/{{ season }}/{{ cur_md|add:"-1"|stringformat:"02i" }}"><span aria-hidden="true">←</span></a></li>
|
|
||||||
{{ cur_md }}. Spieltag
|
|
||||||
<li data-toggle="tooltip" title="{% trans 'next' %}" class="next"><a href="/matchday/{{ ls }}/{{ season }}/{{ cur_md|add:"1"|stringformat:"02i" }}"><span aria-hidden="true">→</span></a></li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<form role="form" action="" method="post">{% csrf_token %}
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-hover table-condensed">
|
|
||||||
<tr>
|
|
||||||
<th>Anstoß</th>
|
|
||||||
<th>Heim</th>
|
|
||||||
<th>Gast</th>
|
|
||||||
<th>Erg.></th>
|
|
||||||
<th colspan="2">Tipp</th>
|
|
||||||
</tr>
|
|
||||||
{% for match in matches %}
|
|
||||||
{% if match.started and not match.finished %}
|
|
||||||
<tr class="danger">{% else %}<tr>{% endif %}
|
|
||||||
<td>{{ match.matchDateTime }}</td>
|
|
||||||
<td><img src="{{ STATIC_URL}}{{ match.iconTeam1 }}" />
|
|
||||||
<span class="hidden-xs"> {{ match.nameTeam1 }}</span>
|
|
||||||
<span class="visible-xs"> {{ match.abbrTeam1 }}</span>
|
|
||||||
</td>
|
|
||||||
<td><img src="{{ STATIC_URL}}{{ match.iconTeam2 }}" />
|
|
||||||
<span class="hidden-xs"> {{ match.nameTeam2 }}</span>
|
|
||||||
<span class="visible-xs"> {{ match.abbrTeam2 }}</span>
|
|
||||||
</td>
|
|
||||||
<td>{{ match.matchResult }}</td>
|
|
||||||
<td>{{ match.tippFormTeam1 }}</td><td>{{ match.tippFormTeam2 }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-default btn-lg btn-block">
|
|
||||||
<span class="glyphicon glyphicon-saved" aria-hidden="true"></span> Tipps abgeben
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-7">
|
|
||||||
<h2>Mitspieler</h2>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-hover table-condensed">
|
|
||||||
<tr>
|
|
||||||
<th>Tipper</th>
|
|
||||||
<th>Gesamt</th>
|
|
||||||
{% for match in matches %}
|
|
||||||
<th><img src="{{ STATIC_URL }}{{ match.iconTeam1 }}" /><br /><br />
|
|
||||||
<img src="{{ STATIC_URL }}{{ match.iconTeam2 }}" /></th>
|
|
||||||
{% endfor %}
|
|
||||||
</tr>
|
|
||||||
{% for mate in tipp_mates %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ mate.mate }}</td>
|
|
||||||
<td>{{ mate.sum_score }}</td>
|
|
||||||
{% for tipp in mate.tipps %}
|
|
||||||
<td>{{ tipp }}</td>
|
|
||||||
{% endfor %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
+5
-2
@@ -9,13 +9,16 @@
|
|||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<span class="navbar-brand">TipPy 1.0</span>
|
<a class="navbar-brand" href="/about">TipPy 1.0</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-collapse collapse">
|
<div class="navbar-collapse collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li><a href="/">Tipps</a></li>
|
<li><a href="/">Tipps</a></li>
|
||||||
<li><a href="/charts/{{ ls }}/{{ season }}{% if pos %}/{{ pos }}{% endif %}">Bestenliste</a></li>
|
<li><a href="/charts/{{ ls }}/{{ season }}{% if pos %}/{{ pos }}{% endif %}">Bestenliste</a></li>
|
||||||
<li><a href="/blog/1">Blog</a></li>
|
<li><a href="/blog/1">Blog</a></li>
|
||||||
|
{% if request.user.is_active and request.user.is_staff %}
|
||||||
|
<li><a href="/staff">Staff</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
{% if has_refresh %}
|
{% if has_refresh %}
|
||||||
@@ -32,7 +35,7 @@
|
|||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="/accounts/profile/{{user.id}}">Profil ändern</a></li>
|
<li><a href="/accounts/profile/{{user.id}}">Profil ändern</a></li>
|
||||||
<li><a href="/accounts/password_change/">Passwort ändern</a></li>
|
<li><a href="/accounts/password_change/">Passwort ändern</a></li>
|
||||||
<li><a href="/logout">Abmelden</a></li>
|
<li><a href="/accounts/logout">Abmelden</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
+47
-38
@@ -1,49 +1,58 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n static %}
|
{% load i18n static %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<title> TipPy Blog</title>
|
<title> TipPy Blog</title>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block nav %}
|
{% block nav %}
|
||||||
{% include "nav.html" with ls=ls season=season %}
|
{% include "nav.html" with ls=ls season=season %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div id="content-main">
|
<div id="content-main">
|
||||||
{% if form.errors %}
|
{% if form_bp.errors %}
|
||||||
<div>
|
<div>
|
||||||
<p class="errornote">
|
<p class="errornote">
|
||||||
{% if form.errors.items|length == 1 %}
|
{% if form_bp.errors.items|length == 1 %}
|
||||||
{% trans "Please correct the error below." %}
|
{% trans "Please correct the error below." %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% trans "Please correct the errors below." %}
|
{% trans "Please correct the errors below." %}
|
||||||
{% endif %}</p>
|
{% endif %}</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<form class="form-horizontal" action="" method="post">{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form_bp.content.errors }}
|
||||||
|
<div class="col-sm-5">
|
||||||
|
<div class="panel-body">
|
||||||
|
<textarea class="form-control" placeholder="Schreibe einen Kommentar..." id="id_content"
|
||||||
|
name="content" maxlength="100" rows="2"></textarea>
|
||||||
|
{% if cnt_mandants > 1 %}
|
||||||
|
{{ form_mandants.mandants.label_tag }}
|
||||||
|
{% for choice in form_mandants.mandants %}
|
||||||
|
<label for="{{ choice.id_for_label }}">
|
||||||
|
{{ choice.tag }} {{ choice.choice_label }}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="submit" class="btn btn-default">{% trans 'Sent' %}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if debug %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<p>{{ debug }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-8">
|
|
||||||
<form class="form-horizontal" action="" method="post">{% csrf_token %}
|
|
||||||
<div class="form-group">
|
|
||||||
{{form.title.errors}}
|
|
||||||
<label for="id_title" class="col-sm-4 control-label required">{% trans 'Title' %}</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<input id="id_title" maxlength="32" name="title" class="form-control" type="text" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
{{form.content.errors}}
|
|
||||||
<label for="id_content" class="col-sm-4 control-label required">{% trans 'Content' %}</label>
|
|
||||||
<div class="col-sm-5">
|
|
||||||
<textarea class="form-control" maxlength="256" rows="2" id="id_content" name="content"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
|
||||||
<button type="submit" class="btn btn-default">{% trans 'Sent' %}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load url from future %}
|
{% load admin_urls %}
|
||||||
|
|
||||||
{% comment %}
|
{% comment %}
|
||||||
Main page to authenticate users.
|
Main page to authenticate users.
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<form class="form-signin" role="form" method="post" action="{% url 'django.contrib.auth.views.login' %}">
|
<form class="form-signin" role="form" method="post" action="{% url 'login' %}">
|
||||||
<h2 class="form-signin-heading">Bitte melde dich an</h2>
|
<h2 class="form-signin-heading">Bitte melde dich an</h2>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input class="form-control" type="text" autofocus="" required="" name="{{form.username.html_name}}" placeholder="Anmeldename" />
|
<input class="form-control" type="text" autofocus="" required="" name="{{form.username.html_name}}" placeholder="Anmeldename" />
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n static %}
|
||||||
|
{% load humanize %}
|
||||||
|
{% block head %}
|
||||||
|
<script type="text/javascript" src="{% static 'javascript/tippy.js' %}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block nav %}
|
||||||
|
{% include "nav.html" with ls=ls season=season %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div id="content-main">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h3>Wettbewerbe</h3>
|
||||||
|
{% for comp in competitions %}
|
||||||
|
{{ comp }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
<h3></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if debug %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h2 class="form-signin-heading">{% trans 'Debug' %}</h2>
|
||||||
|
{% for line in debug %}
|
||||||
|
<p>{{ line }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
+4
-7
@@ -18,24 +18,20 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with TipPy. If not, see <http://www.gnu.org/licenses/>.
|
along with TipPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from tipp.models import Team, Match, Tipp, Score, Mandant, RelUserMandant, Competition, Post, UserProfile
|
from tipp.models import *
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
class PostAdmin(admin.ModelAdmin):
|
class PostAdmin(admin.ModelAdmin):
|
||||||
# fields display on change list
|
# fields display on change list
|
||||||
list_display = ['title']
|
list_display = ['content']
|
||||||
# fields to filter the change list with
|
# fields to filter the change list with
|
||||||
list_filter = ['published', 'created']
|
list_filter = ['published', 'created']
|
||||||
# fields to search in change list
|
# fields to search in change list
|
||||||
search_fields = ['title', 'content']
|
search_fields = ['content']
|
||||||
# enable the date drill down on change list
|
# enable the date drill down on change list
|
||||||
date_hierarchy = 'created'
|
date_hierarchy = 'created'
|
||||||
# enable the save buttons on top on change form
|
# enable the save buttons on top on change form
|
||||||
save_on_top = True
|
save_on_top = True
|
||||||
# prepopulate the slug from the title - big timesaver!
|
|
||||||
prepopulated_fields = {"slug": ("title",)}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Team)
|
admin.site.register(Team)
|
||||||
admin.site.register(Match)
|
admin.site.register(Match)
|
||||||
@@ -45,4 +41,5 @@ admin.site.register(Score)
|
|||||||
admin.site.register(RelUserMandant)
|
admin.site.register(RelUserMandant)
|
||||||
admin.site.register(Competition)
|
admin.site.register(Competition)
|
||||||
admin.site.register(Post, PostAdmin)
|
admin.site.register(Post, PostAdmin)
|
||||||
|
admin.site.register(RelPostMandant)
|
||||||
|
|
||||||
|
|||||||
+25
-14
@@ -22,31 +22,42 @@ from django import forms
|
|||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.files.images import get_image_dimensions
|
from django.core.files.images import get_image_dimensions
|
||||||
from tipp.models import Match, Competition, Post, UserProfile
|
from tipp.models import Match, Competition, Post, UserProfile, \
|
||||||
|
Mandant, RelUserMandant
|
||||||
|
|
||||||
class NumberInput(forms.TextInput):
|
class NumberInput(forms.TextInput):
|
||||||
input_type = 'number'
|
input_type = 'number'
|
||||||
|
|
||||||
class TippForm(forms.Form):
|
class TippForm(forms.Form):
|
||||||
tippTeam1 = forms.IntegerField(required=True,widget=NumberInput(attrs={
|
tippTeam1 = forms.IntegerField(required=True,widget=NumberInput(
|
||||||
'cols': '2',
|
attrs={
|
||||||
'min': '0', 'max': '99', 'step': '1',
|
'cols': '2',
|
||||||
'class':'form-inline',
|
'min': '0', 'max': '99', 'step': '1',
|
||||||
'role': 'form'}
|
'class':'form-inline',
|
||||||
|
'role': 'form'
|
||||||
|
}
|
||||||
))
|
))
|
||||||
tippTeam2 = forms.IntegerField(required=True,widget=NumberInput(attrs={
|
tippTeam2 = forms.IntegerField(required=True,widget=NumberInput(
|
||||||
'cols': '2',
|
attrs={
|
||||||
'min': '0', 'max': '99', 'step': '1',
|
'cols': '2',
|
||||||
'class':'form-inline',
|
'min': '0', 'max': '99', 'step': '1',
|
||||||
'role': 'form'}
|
'class':'form-inline',
|
||||||
|
'role': 'form'
|
||||||
|
}
|
||||||
))
|
))
|
||||||
tippTeam1.widget.attrs['style'] = "width:35px"
|
tippTeam1.widget.attrs['style'] = "width:45px"
|
||||||
tippTeam2.widget.attrs['style'] = "width:35px"
|
tippTeam2.widget.attrs['style'] = "width:45px"
|
||||||
|
|
||||||
class BlogpostForm(ModelForm):
|
class BlogpostForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Post
|
model = Post
|
||||||
fields = ['title', 'content']
|
fields = ['content']
|
||||||
|
|
||||||
|
class MandantsForm(forms.Form):
|
||||||
|
mandants = forms.MultipleChoiceField(
|
||||||
|
label= "Posten in",
|
||||||
|
widget=forms.CheckboxSelectMultiple({'checked':'checked'})
|
||||||
|
)
|
||||||
|
|
||||||
class UserForm(forms.ModelForm):
|
class UserForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
# Generated by Django 4.0.6 on 2022-07-14 15:15
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Competition',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('leagueShortcut', models.CharField(max_length=32)),
|
||||||
|
('leagueName', models.CharField(max_length=128)),
|
||||||
|
('season', models.CharField(max_length=4)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Mandant',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=32, unique=True)),
|
||||||
|
('description', models.CharField(max_length=255)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Post',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('content', models.TextField()),
|
||||||
|
('published', models.BooleanField(default=True)),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['-created'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Team',
|
||||||
|
fields=[
|
||||||
|
('teamID', models.IntegerField(primary_key=True, serialize=False, unique=True)),
|
||||||
|
('name', models.CharField(max_length=200)),
|
||||||
|
('icon', models.FileField(upload_to='images/team_logos/')),
|
||||||
|
('abbr', models.CharField(max_length=3)),
|
||||||
|
('iconURL', models.CharField(max_length=2000)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'managed': True,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserProfile',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('avatar', models.ImageField(blank=True, upload_to='profiles/')),
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Score',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('exact_high', models.PositiveSmallIntegerField()),
|
||||||
|
('exact', models.PositiveSmallIntegerField()),
|
||||||
|
('diff', models.PositiveSmallIntegerField()),
|
||||||
|
('tendency', models.PositiveSmallIntegerField()),
|
||||||
|
('client', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tipp.mandant')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Match',
|
||||||
|
fields=[
|
||||||
|
('matchID', models.IntegerField(primary_key=True, serialize=False, unique=True)),
|
||||||
|
('matchDateTime', models.DateTimeField()),
|
||||||
|
('group', models.IntegerField()),
|
||||||
|
('matchday', models.IntegerField()),
|
||||||
|
('matchday_name', models.CharField(max_length=128)),
|
||||||
|
('pointsTeam1', models.SmallIntegerField()),
|
||||||
|
('pointsTeam2', models.SmallIntegerField()),
|
||||||
|
('finished', models.BooleanField()),
|
||||||
|
('season', models.CharField(max_length=4)),
|
||||||
|
('leagueShortcut', models.CharField(max_length=12)),
|
||||||
|
('idTeam1', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='tipp.team')),
|
||||||
|
('idTeam2', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='tipp.team')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tipp',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('pointsTeam1', models.PositiveSmallIntegerField()),
|
||||||
|
('pointsTeam2', models.PositiveSmallIntegerField()),
|
||||||
|
('score', models.PositiveIntegerField(blank=True, null=True)),
|
||||||
|
('matchID', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tipp.match')),
|
||||||
|
('tipperID', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('matchID', 'tipperID')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RelUserMandant',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('mandant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tipp.mandant')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('user', 'mandant')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RelPostMandant',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('mandant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tipp.mandant')),
|
||||||
|
('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tipp.post')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('post', 'mandant')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='chart',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('points', models.PositiveSmallIntegerField()),
|
||||||
|
('diff', models.SmallIntegerField()),
|
||||||
|
('games', models.PositiveSmallIntegerField()),
|
||||||
|
('competition', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tipp.competition')),
|
||||||
|
('team', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tipp.team')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('team', 'competition')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
+100
-35
@@ -17,115 +17,180 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with TipPy. If not, see <http://www.gnu.org/licenses/>.
|
along with TipPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.db import models
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
class UserProfile(models.Model):
|
class UserProfile(models.Model):
|
||||||
user = models.OneToOneField(User)
|
user = models.OneToOneField(
|
||||||
|
User,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
avatar = models.ImageField(upload_to="profiles/", blank=True)
|
avatar = models.ImageField(upload_to="profiles/", blank=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.user.username
|
return self.user.username
|
||||||
|
|
||||||
|
|
||||||
class Competition(models.Model):
|
class Competition(models.Model):
|
||||||
leagueShortcut = models.CharField(max_length=32)
|
leagueShortcut = models.CharField(max_length=32)
|
||||||
leagueName = models.CharField(max_length=128)
|
leagueName = models.CharField(max_length=128)
|
||||||
season = models.CharField(max_length=4)
|
season = models.CharField(max_length=4)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = ("leagueShortcut", "season")
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return(self.leagueShortcut)
|
return (self.leagueShortcut)
|
||||||
|
|
||||||
|
|
||||||
class Team(models.Model):
|
class Team(models.Model):
|
||||||
teamID = models.IntegerField(unique=True, primary_key=True)
|
teamID = models.IntegerField(unique=True, primary_key=True)
|
||||||
name = models.CharField(max_length=200)
|
name = models.CharField(max_length=200)
|
||||||
icon = models.FileField(upload_to="images/team_logos/")
|
icon = models.FileField(upload_to="images/team_logos/")
|
||||||
abbr = models.CharField(max_length=3)
|
abbr = models.CharField(max_length=3)
|
||||||
|
iconURL = models.CharField(max_length=2000)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = True
|
||||||
|
app_label = 'tipp'
|
||||||
|
|
||||||
|
|
||||||
class Match(models.Model):
|
class Match(models.Model):
|
||||||
matchID = models.IntegerField(unique=True,primary_key=True)
|
matchID = models.IntegerField(unique=True, primary_key=True)
|
||||||
matchDateTime = models.DateTimeField()
|
matchDateTime = models.DateTimeField()
|
||||||
group = models.IntegerField()
|
group = models.IntegerField()
|
||||||
matchday = models.IntegerField()
|
matchday = models.IntegerField()
|
||||||
idTeam1 = models.ForeignKey(Team, related_name='+')
|
matchday_name = models.CharField(max_length=128)
|
||||||
idTeam2 = models.ForeignKey(Team, related_name='+')
|
|
||||||
|
competition = models.ForeignKey(
|
||||||
|
Competition,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
|
||||||
|
idTeam1 = models.ForeignKey(
|
||||||
|
Team, related_name='+',
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
idTeam2 = models.ForeignKey(
|
||||||
|
Team, related_name='+',
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
|
||||||
pointsTeam1 = models.SmallIntegerField()
|
pointsTeam1 = models.SmallIntegerField()
|
||||||
pointsTeam2 = models.SmallIntegerField()
|
pointsTeam2 = models.SmallIntegerField()
|
||||||
finished = models.BooleanField()
|
finished = models.BooleanField()
|
||||||
season = models.CharField(max_length=4)
|
|
||||||
leagueShortcut = models.CharField(max_length=12)
|
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
"""
|
|
||||||
return (str(self.matchID) +
|
|
||||||
str(Team.objects.get(teamID=int(self.idTeam1)).values(name)) + " - " +
|
|
||||||
str(Team.objects.get(teamID=int(self.idTeam2)).values(name)))
|
|
||||||
"""
|
|
||||||
return (str(self.matchID))
|
return (str(self.matchID))
|
||||||
|
|
||||||
|
|
||||||
class Tipp(models.Model):
|
class Tipp(models.Model):
|
||||||
matchID = models.ForeignKey(Match)
|
matchID = models.ForeignKey(
|
||||||
tipperID = models.ForeignKey(User)
|
Match,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
tipperID = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
pointsTeam1 = models.PositiveSmallIntegerField()
|
pointsTeam1 = models.PositiveSmallIntegerField()
|
||||||
pointsTeam2 = models.PositiveSmallIntegerField()
|
pointsTeam2 = models.PositiveSmallIntegerField()
|
||||||
score = models.PositiveIntegerField(blank=True, null=True)
|
score = models.PositiveIntegerField(
|
||||||
|
blank=True, null=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ("matchID", "tipperID")
|
unique_together = ("matchID", "tipperID")
|
||||||
|
|
||||||
|
|
||||||
class Mandant(models.Model):
|
class Mandant(models.Model):
|
||||||
name = models.CharField(max_length=32, unique=True)
|
name = models.CharField(max_length=32, unique=True)
|
||||||
description = models.CharField(max_length=255)
|
description = models.CharField(max_length=255)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class Score(models.Model):
|
class Score(models.Model):
|
||||||
client = models.ForeignKey(Mandant)
|
client = models.ForeignKey(
|
||||||
|
Mandant,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
exact_high = models.PositiveSmallIntegerField()
|
exact_high = models.PositiveSmallIntegerField()
|
||||||
exact = models.PositiveSmallIntegerField()
|
exact = models.PositiveSmallIntegerField()
|
||||||
diff = models.PositiveSmallIntegerField()
|
diff = models.PositiveSmallIntegerField()
|
||||||
tendency = models.PositiveSmallIntegerField()
|
tendency = models.PositiveSmallIntegerField()
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return str(self.client)
|
return str(self.client)
|
||||||
|
|
||||||
class chart(models.Model):
|
|
||||||
team = models.ForeignKey(Team)
|
class Chart(models.Model):
|
||||||
competition = models.ForeignKey(Competition)
|
team = models.ForeignKey(
|
||||||
|
Team,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
competition = models.ForeignKey(
|
||||||
|
Competition,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
points = models.PositiveSmallIntegerField()
|
points = models.PositiveSmallIntegerField()
|
||||||
diff = models.SmallIntegerField()
|
diff = models.SmallIntegerField()
|
||||||
games = models.PositiveSmallIntegerField()
|
games = models.PositiveSmallIntegerField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ("team", "competition")
|
unique_together = ("team", "competition")
|
||||||
|
|
||||||
|
|
||||||
class RelUserMandant(models.Model):
|
class RelUserMandant(models.Model):
|
||||||
user = models.ForeignKey(User)
|
user = models.ForeignKey(
|
||||||
mandant = models.ForeignKey(Mandant)
|
User,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
mandant = models.ForeignKey(
|
||||||
|
Mandant,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ("user", "mandant")
|
unique_together = ("user", "mandant")
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return (str(self.user) + " -> " + str(self.mandant))
|
return (str(self.user) + " -> " + str(self.mandant))
|
||||||
|
|
||||||
|
|
||||||
class Post(models.Model):
|
class Post(models.Model):
|
||||||
title = models.CharField(max_length=255, null=False, blank=False)
|
|
||||||
slug = models.SlugField(unique=True, max_length=255)
|
|
||||||
content = models.TextField()
|
content = models.TextField()
|
||||||
published = models.BooleanField(default=True)
|
published = models.BooleanField(default=True)
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
author = models.ForeignKey(User)
|
author = models.ForeignKey(
|
||||||
|
User,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-created']
|
ordering = ['-created']
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u'%s' % self.title
|
return u'%s' % self.created
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse('tipp.views.blogpost', args=[self.slug])
|
|
||||||
|
|
||||||
|
|
||||||
|
class RelPostMandant(models.Model):
|
||||||
|
post = models.ForeignKey(
|
||||||
|
Post,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
mandant = models.ForeignKey(
|
||||||
|
Mandant,
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = ("post", "mandant")
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return (str(self.post) + " -> " + str(self.mandant))
|
||||||
|
|||||||
Executable → Regular
+45
-30
@@ -2,69 +2,84 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2015-2016 by Martin Bley (martin@mb-oss.de)
|
# Copyright (c) 2015-2016 by Martin Bley (martin@mb-oss.de)
|
||||||
#
|
#
|
||||||
# This file is part of TipPy.
|
# This file is part of TipPy.
|
||||||
#
|
#
|
||||||
# TipPy is free software: you can redistribute it and/or modify
|
# TipPy is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# TipPy is distributed in the hope that it will be useful,
|
# TipPy is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with TipPy. If not, see <http://www.gnu.org/licenses/>.
|
# along with TipPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import sys, locale, suds, urllib2, psycopg2
|
import locale
|
||||||
|
import urllib.error
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
from zeep import Client
|
||||||
|
from zeep.transports import Transport
|
||||||
|
from requests import Session
|
||||||
|
|
||||||
|
|
||||||
class OpenLiga(object):
|
class OpenLiga(object):
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
error = ""
|
error = ""
|
||||||
proxyurl = None
|
proxyurl = None
|
||||||
debug = None
|
debug = None
|
||||||
client = None
|
client = None
|
||||||
|
|
||||||
def __init__(self, proxyurl=None, debug=False):
|
def __init__(self, proxyurl=None, debug=False):
|
||||||
|
|
||||||
# set locale to environment (for dispaying localized dates)
|
# set locale to environment (for dispaying localized dates)
|
||||||
locale.setlocale(locale.LC_TIME, "")
|
locale.setlocale(locale.LC_TIME, "")
|
||||||
|
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
|
|
||||||
# get a SUDS client object
|
# get a SOAP client object
|
||||||
if self.proxyurl is None:
|
wsdl_url = 'http://www.openligadb.de/Webservices/Sportsdata.asmx?WSDL'
|
||||||
try:
|
|
||||||
self.client = suds.client.Client('http://www.openligadb.de/Webservices/Sportsdata.asmx?WSDL')
|
try:
|
||||||
except (urllib2.URLError):
|
if proxyurl is None:
|
||||||
self.error += "Connect to webservice failed."
|
self.client = Client(wsdl=wsdl_url)
|
||||||
else:
|
else:
|
||||||
try:
|
session = Session()
|
||||||
t = suds.transport.http.HttpTransport()
|
session.proxies = {'http': proxyurl, 'https': proxyurl}
|
||||||
proxy = urllib2.ProxyHandler({'http':proxyurl})
|
transport = Transport(session=session)
|
||||||
opener = urllib2.build_opener(proxy)
|
self.client = Client(wsdl=wsdl_url, transport=transport)
|
||||||
t.urlopener = opener
|
except (urllib.error.URLError, Exception) as e:
|
||||||
self.client = suds.client.Client('http://www.openligadb.de/Webservices/Sportsdata.asmx?WSDL', transport=t)
|
self.error += f"Connect to webservice failed: {str(e)}\n"
|
||||||
except urllib2.URLError as e:
|
|
||||||
self.error += "Connect to webservice failed (via proxy " + proxyurl + "): " + str(e) + "\n"
|
|
||||||
|
|
||||||
def getSeason(self, season, league='bl1'):
|
def getSeason(self, season, league='bl1'):
|
||||||
""" Get the whole season.
|
""" Get the whole season.
|
||||||
|
|
||||||
Args: season and league shortcut (optional)
|
Args: season and league shortcut (optional)
|
||||||
"""
|
"""
|
||||||
return(self.client.service.GetMatchdataByLeagueSaison(leagueShortcut=league,leagueSaison=season))
|
return self.client.service.GetMatchdataByLeagueSaison(
|
||||||
|
leagueShortcut=league, leagueSaison=season)
|
||||||
|
|
||||||
def getMatchday(self, season, matchdaynumber, league='bl1'):
|
def getMatchday(self, season, matchdaynumber, league='bl1'):
|
||||||
""" Get matchday.
|
""" Get matchday.
|
||||||
|
|
||||||
Args: season, matchdaynumber and league shortcut (optional)
|
Args: season, matchdaynumber and league shortcut (optional)
|
||||||
"""
|
"""
|
||||||
return(self.client.service.GetMatchdataByGroupLeagueSaison(groupOrderID=matchdaynumber,leagueShortcut=league,leagueSaison=season))
|
return self.client.service.GetMatchdataByGroupLeagueSaison(
|
||||||
|
groupOrderID=matchdaynumber,
|
||||||
|
leagueShortcut=league,
|
||||||
|
leagueSaison=season)
|
||||||
|
|
||||||
def getTeams(self, season, league='bl1'):
|
def getTeams(self, season, league='bl1'):
|
||||||
return(self.client.service.GetTeamsByLeagueSaison(leagueShortcut=league,leagueSaison=season))
|
return self.client.service.GetTeamsByLeagueSaison(
|
||||||
|
leagueShortcut=league,
|
||||||
|
leagueSaison=season)
|
||||||
|
|
||||||
|
def getCurrentGroup(self, league):
|
||||||
|
return self.client.service.GetCurrentGroup(
|
||||||
|
leagueShortcut=league)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
This file demonstrates writing tests using the unittest module. These will pass
|
This file demonstrates writing tests using the unittest module.
|
||||||
when you run "manage.py test".
|
These will pass when you run "manage.py test".
|
||||||
|
|
||||||
Replace this with more appropriate tests for your application.
|
Replace this with more appropriate tests for your application.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
from django.contrib.auth import views as auth_views
|
||||||
|
from django.urls import re_path
|
||||||
|
from django.conf.urls import include
|
||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls.static import static
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
re_path(r'^$', views.home, name='home'),
|
||||||
|
re_path(r'^getSeason/(?P<ls>.*)/(?P<season>\d{4})$',
|
||||||
|
views.getSeason),
|
||||||
|
re_path(r'^update/(?P<ls>.*)/(?P<season>\d{4})/(?P<cur_md>\d{2})$',
|
||||||
|
views.update, name='update'),
|
||||||
|
re_path(r'^matchday/(?P<ls>.{3,})/(?P<season>\d{4})/(?P<matchday>\d{2})$',
|
||||||
|
views.matchday, name='matchday'),
|
||||||
|
re_path(r'^charts/(?P<ls>\w{3,})/(?P<season>\d{4})$', views.charts,
|
||||||
|
name='charts'),
|
||||||
|
re_path(r'^charts/(?P<ls>\w{3,})/(?P<season>\d{4})/(?P<pos>\w{1,})$',
|
||||||
|
views.charts, name='charts'),
|
||||||
|
re_path(r'^accounts/profile/(\d+)', views.profile),
|
||||||
|
re_path(r'^accounts/', include('django.contrib.auth.urls')),
|
||||||
|
re_path(r'^blog/newpost$', views.newBlogpost),
|
||||||
|
re_path(r'^blog/(?P<page>\d)$', views.blogindex),
|
||||||
|
re_path(r'^about$', views.about),
|
||||||
|
re_path(r'^staff', views.staff),
|
||||||
|
re_path(r'^accounts/login/', auth_views.LoginView.as_view()),
|
||||||
|
re_path(r'^accounts/logout/', auth_views.LogoutView.as_view())
|
||||||
|
]
|
||||||
|
# Redirect on logout
|
||||||
|
LOGOUT_REDIRECT_URL = "home"
|
||||||
|
if settings.DEBUG is True:
|
||||||
|
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
+661
-372
File diff suppressed because it is too large
Load Diff
@@ -1,188 +0,0 @@
|
|||||||
"""
|
|
||||||
Django settings for tippy project.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/1.7/topics/settings/
|
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
|
||||||
https://docs.djangoproject.com/en/1.7/ref/settings/
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
|
||||||
import os
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
|
||||||
|
|
||||||
# Django settings for tippy project.
|
|
||||||
DEBUG = True
|
|
||||||
TEMPLATE_DEBUG = DEBUG
|
|
||||||
|
|
||||||
ADMINS = (
|
|
||||||
('Martin Bley', 'martin@mb-oss.de'),
|
|
||||||
)
|
|
||||||
|
|
||||||
MANAGERS = ADMINS
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
|
||||||
'NAME': 'django_tippy',
|
|
||||||
'USER': 'tippy',
|
|
||||||
'PASSWORD': 'tippy',
|
|
||||||
'HOST': 'localhost',
|
|
||||||
'PORT': '5432',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Hosts/domain names that are valid for this site; required if DEBUG is False
|
|
||||||
# See https://docs.djangoproject.com/en/1.4/ref/settings/#allowed-hosts
|
|
||||||
ALLOWED_HOSTS = ['*']
|
|
||||||
|
|
||||||
# Local time zone for this installation. Choices can be found here:
|
|
||||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
|
||||||
# although not all choices may be available on all operating systems.
|
|
||||||
# In a Windows environment this must be set to your system time zone.
|
|
||||||
TIME_ZONE = 'Europe/Berlin'
|
|
||||||
|
|
||||||
# Language code for this installation. All choices can be found here:
|
|
||||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
|
||||||
LANGUAGE_CODE = 'de-de'
|
|
||||||
|
|
||||||
SITE_ID = 1
|
|
||||||
|
|
||||||
# If you set this to False, Django will make some optimizations so as not
|
|
||||||
# to load the internationalization machinery.
|
|
||||||
USE_I18N = True
|
|
||||||
|
|
||||||
# If you set this to False, Django will not format dates, numbers and
|
|
||||||
# calendars according to the current locale.
|
|
||||||
USE_L10N = True
|
|
||||||
|
|
||||||
# If you set this to False, Django will not use timezone-aware datetimes.
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
|
||||||
# Example: "/home/media/media.lawrence.com/media/"
|
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
|
|
||||||
|
|
||||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
|
||||||
# trailing slash.
|
|
||||||
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
|
|
||||||
MEDIA_URL = '/media/'
|
|
||||||
|
|
||||||
# Absolute path to the directory static files should be collected to.
|
|
||||||
# Don't put anything in this directory yourself; store your static files
|
|
||||||
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
|
|
||||||
# Example: "/home/media/media.lawrence.com/static/"
|
|
||||||
STATIC_ROOT = '/home/martin/dev/tippy/TipPy/static/'
|
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
|
|
||||||
|
|
||||||
# URL prefix for static files.
|
|
||||||
# Example: "http://media.lawrence.com/static/"
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
|
|
||||||
# Additional locations of static files
|
|
||||||
STATICFILES_DIRS = (
|
|
||||||
# Put strings here, like "/home/html/static" or "C:/www/django/static".
|
|
||||||
# Always use forward slashes, even on Windows.
|
|
||||||
# Don't forget to use absolute paths, not relative paths.
|
|
||||||
'/home/martin/dev/tippy/TipPy/tippy/static',
|
|
||||||
)
|
|
||||||
|
|
||||||
# List of finder classes that know how to find static files in
|
|
||||||
# various locations.
|
|
||||||
STATICFILES_FINDERS = (
|
|
||||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
|
||||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
|
||||||
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
|
||||||
)
|
|
||||||
|
|
||||||
# Make this unique, and don't share it with anybody.
|
|
||||||
SECRET_KEY = '-7%ge^nl1b0t0694%ws&0$ft_lo)j4l1f-qv#ku^=$)s(sw6us'
|
|
||||||
|
|
||||||
# List of callables that know how to import templates from various sources.
|
|
||||||
TEMPLATE_LOADERS = (
|
|
||||||
'django.template.loaders.filesystem.Loader',
|
|
||||||
'django.template.loaders.app_directories.Loader',
|
|
||||||
# 'django.template.loaders.eggs.Loader',
|
|
||||||
)
|
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
|
||||||
# Uncomment the next line for simple clickjacking protection:
|
|
||||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
||||||
)
|
|
||||||
|
|
||||||
ROOT_URLCONF = 'tippy.urls'
|
|
||||||
|
|
||||||
# Python dotted path to the WSGI application used by Django's runserver.
|
|
||||||
WSGI_APPLICATION = 'tippy.wsgi.application'
|
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
|
||||||
[os.path.join(BASE_DIR, 'templates')]
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
|
||||||
'django.contrib.auth',
|
|
||||||
'django.contrib.contenttypes',
|
|
||||||
'django.contrib.sessions',
|
|
||||||
'django.contrib.sites',
|
|
||||||
'django.contrib.messages',
|
|
||||||
'django.contrib.staticfiles',
|
|
||||||
'django.contrib.humanize',
|
|
||||||
# Uncomment the next line to enable the admin:
|
|
||||||
'django.contrib.admin',
|
|
||||||
# Uncomment the next line to enable admin documentation:
|
|
||||||
'django.contrib.admindocs',
|
|
||||||
'tipp',
|
|
||||||
)
|
|
||||||
|
|
||||||
# URL of the login page.
|
|
||||||
LOGIN_URL = '/login'
|
|
||||||
|
|
||||||
# A sample logging configuration. The only tangible logging
|
|
||||||
# performed by this configuration is to send an email to
|
|
||||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
|
||||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
|
||||||
# more details on how to customize your logging configuration.
|
|
||||||
LOGGING = {
|
|
||||||
'version': 1,
|
|
||||||
'disable_existing_loggers': False,
|
|
||||||
'filters': {
|
|
||||||
'require_debug_false': {
|
|
||||||
'()': 'django.utils.log.RequireDebugFalse'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'handlers': {
|
|
||||||
'mail_admins': {
|
|
||||||
'level': 'ERROR',
|
|
||||||
'filters': ['require_debug_false'],
|
|
||||||
'class': 'django.utils.log.AdminEmailHandler'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'loggers': {
|
|
||||||
'django.request': {
|
|
||||||
'handlers': ['mail_admins'],
|
|
||||||
'level': 'ERROR',
|
|
||||||
'propagate': True,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EMAIL_USE_TLS = True
|
|
||||||
EMAIL_HOST = 'hermes.mb-oss.de'
|
|
||||||
EMAIL_PORT = 25
|
|
||||||
EMAIL_HOST_USER = 'tippy@mb-oss.de'
|
|
||||||
#EMAIL_HOST_PASSWORD = 'p@ssword'
|
|
||||||
|
|
||||||
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
|
|
||||||
SERVER_EMAIL = EMAIL_HOST_USER
|
|
||||||
|
|
||||||
SESSION_COOKIE_AGE = 7200
|
|
||||||
|
|
||||||
AUTH_PROFILE_MODULE = 'tippy.UserProfile'
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
from django.conf.urls import patterns, include, url
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
# Uncomment the next two lines to enable the admin:
|
|
||||||
from django.contrib import admin
|
|
||||||
admin.autodiscover()
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
|
||||||
# Examples:
|
|
||||||
url(r'^$', 'tipp.views.home', name='home'),
|
|
||||||
url(r'^login$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
|
|
||||||
url(r'^logout$', 'django.contrib.auth.views.logout', {'next_page': '/'}),
|
|
||||||
url(r'^update/(?P<ls>.*)/(?P<season>\d{4})/(?P<cur_md>\d{2})$', 'tipp.views.update', name='update'),
|
|
||||||
url(r'^matchday/(?P<ls>.{3,})/(?P<season>\d{4})/(?P<matchday>\d{2})$', 'tipp.views.matchday', name='matchday'),
|
|
||||||
url(r'^charts/(?P<ls>\w{3,})/(?P<season>\d{4})$', 'tipp.views.charts', name='charts'),
|
|
||||||
url(r'^charts/(?P<ls>\w{3,})/(?P<season>\d{4})/(?P<pos>\w{1,})$', 'tipp.views.charts', name='charts'),
|
|
||||||
url(r'^accounts/profile/(\d+)', 'tipp.views.profile'),
|
|
||||||
url(r'^accounts/', include('django.contrib.auth.urls')),
|
|
||||||
url(r'^blog/newpost$', 'tipp.views.newBlogpost'),
|
|
||||||
url(r'^blog/(?P<page>\d)$', 'tipp.views.blogindex'),
|
|
||||||
url(r'^blog/(?P<slug>[\w\-]+)', 'tipp.views.blogpost'),
|
|
||||||
|
|
||||||
# Uncomment the admin/doc line below to enable admin documentation:
|
|
||||||
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
|
||||||
|
|
||||||
# Uncomment the next line to enable the admin:
|
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
|
||||||
)
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
|
||||||
urlpatterns += patterns('',
|
|
||||||
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
|
|
||||||
'document_root': settings.MEDIA_ROOT,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
"""
|
|
||||||
WSGI config for tippy project.
|
|
||||||
|
|
||||||
This module contains the WSGI application used by Django's development server
|
|
||||||
and any production WSGI deployments. It should expose a module-level variable
|
|
||||||
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
|
|
||||||
this application via the ``WSGI_APPLICATION`` setting.
|
|
||||||
|
|
||||||
Usually you will have the standard Django WSGI application here, but it also
|
|
||||||
might make sense to replace the whole Django WSGI application with a custom one
|
|
||||||
that later delegates to the Django one. For example, you could introduce WSGI
|
|
||||||
middleware here, or combine a Django application with an application of another
|
|
||||||
framework.
|
|
||||||
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tippy.settings")
|
|
||||||
|
|
||||||
# This application object is used by any WSGI server configured to use this
|
|
||||||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
|
||||||
# setting points here.
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
|
||||||
application = get_wsgi_application()
|
|
||||||
|
|
||||||
# Apply WSGI middleware here.
|
|
||||||
# from helloworld.wsgi import HelloWorldApplication
|
|
||||||
# application = HelloWorldApplication(application)
|
|
||||||
Reference in New Issue
Block a user