5 Commits
Author SHA1 Message Date
Martin Bley 3322649f05 Code optimizsations 2026-09-19 09:04:26 +02:00
Martin Bley 6b99dd5250 venv is running 2026-09-19 07:58:45 +02:00
Martin Bley d4dbd3d9da Updatet venv 2026-09-19 07:32:04 +02:00
Martin Bley 5b7f847bc6 Models optimiert 2026-09-13 08:51:38 +02:00
Martin Bley 99eaafff00 - 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'
2023-04-02 21:24:20 +02:00
13 changed files with 735 additions and 498 deletions
+45 -9
View File
@@ -1,10 +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/
warnings.txt .idea/
*.swp
*.swo
*~
# Umgebungsvariablen
.env
.env.local
+6
View File
@@ -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'
+2 -12
View File
@@ -16,7 +16,6 @@ import os
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
@@ -28,9 +27,7 @@ DEBUG = True
ALLOWED_HOSTS = [] ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
@@ -77,10 +74,9 @@ WSGI_APPLICATION = 'TipPy.wsgi.application'
# Database # Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases # https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2', 'ENGINE': 'django.db.backends.postgresql',
'NAME': 'tippy', 'NAME': 'tippy',
'USER': 'tippy', 'USER': 'tippy',
'PASSWORD': 'tippy', 'PASSWORD': 'tippy',
@@ -91,7 +87,6 @@ DATABASES = {
# Password validation # Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
@@ -109,13 +104,9 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/ # https://docs.djangoproject.com/en/4.0/topics/i18n/
LANGUAGE_CODE = 'de-de' LANGUAGE_CODE = 'de-de'
TIME_ZONE = 'Europe/Berlin' TIME_ZONE = 'Europe/Berlin'
USE_I18N = True USE_I18N = True
USE_TZ = True USE_TZ = True
# Absolute filesystem path to the directory that will hold user-uploaded files. # Absolute filesystem path to the directory that will hold user-uploaded files.
@@ -149,8 +140,7 @@ STATICFILES_DIRS = [
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Redirect on logout # Redirect on logout
LOGOUT_REDIRECT_URL = "home" LOGOUT_REDIRECT_URL = "home"
Executable
+23
View File
@@ -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()
+8 -6
View File
@@ -1,6 +1,8 @@
Django~=4.0.6 asgiref==3.12.1
psycopg2~=2.9.3 Django==6.1.1
suds~=1.1.2 pillow==12.3.0
Pillow~=9.2.0 psycopg2==2.9.13
pytz~=2022.1 pytz==2026.3.post1
urllib3~=1.26.10 sqlparse==0.6.0
suds-community==1.2.0
urllib3==2.8.0
+2 -2
View File
@@ -36,7 +36,7 @@
<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 'js/bootstrap.min.js'%}"></script> <script src="{% static 'js/bootstrap.min.js'%}"></script>
@@ -53,7 +53,7 @@
<div class="col-md-7"> <div class="col-md-7">
<p> <p>
<div class="pull-left"> <div class="pull-left">
© Martin Bley, 2014-2022 | Dank an © Martin Bley, 2014-2023 | Dank an
<a href="http://openligadb.de">OpenLigaDB</a> für die Bereitstellung der <a href="http://openligadb.de">OpenLigaDB</a> für die Bereitstellung der
Spielergebnisse. Spielergebnisse.
</div> </div>
+9 -14
View File
@@ -12,8 +12,8 @@
{% 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>Deine Tipps</h2> <h3>Deine Tipps</h3>
<nav> <nav>
<ul class="pager"> <ul class="pager">
<li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous"><a <li data-toggle="tooltip" title="{% trans 'previous' %}" class="previous"><a
@@ -67,12 +67,9 @@
<span class="glyphicon glyphicon-saved" aria-hidden="true"></span> Tipps abgeben <span class="glyphicon glyphicon-saved" aria-hidden="true"></span> Tipps abgeben
</button> </button>
</form> </form>
</div>
</div> {% for mandant, list in mandant_dict.items %}
<div class="row"> <h3>Mitspieler {{ mandant }}</h3>
{% for mandant, list in mandant_dict.items %}
<div class="col-md-7">
<h4>Mitspieler {{ mandant }}</h4>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover table-condensed"> <table class="table table-hover table-condensed">
<tr> <tr>
@@ -105,12 +102,10 @@
</tr> </tr>
</table> </table>
</div> </div>
</div> {% endfor %}
{% endfor %} </div>
</div> <div class="col-md-6">
<div class="row"> <h3>Chat</h3>
<div class="col-md-7">
<h2>Chat</h2>
{% block chat %} {% block chat %}
{% include "chat.xhtml" with posts=posts %} {% include "chat.xhtml" with posts=posts %}
{% endblock %} {% endblock %}
+3
View File
@@ -16,6 +16,9 @@
<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 %}
+34
View File
@@ -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 %}
+34 -14
View File
@@ -17,9 +17,9 @@ 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.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 = models.OneToOneField(
@@ -30,14 +30,19 @@ class UserProfile(models.Model):
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)
@@ -50,16 +55,22 @@ class Team(models.Model):
return self.name return self.name
class Meta: class Meta:
managed = True managed = True
app_label = 'tipp' 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()
matchday_name = models.CharField(max_length=128) matchday_name = models.CharField(max_length=128)
competition = models.ForeignKey(
Competition,
on_delete=models.CASCADE
)
idTeam1 = models.ForeignKey( idTeam1 = models.ForeignKey(
Team, related_name='+', Team, related_name='+',
on_delete=models.CASCADE on_delete=models.CASCADE
@@ -68,15 +79,15 @@ class Match(models.Model):
Team, related_name='+', Team, related_name='+',
on_delete=models.CASCADE 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)) return (str(self.matchID))
class Tipp(models.Model): class Tipp(models.Model):
matchID = models.ForeignKey( matchID = models.ForeignKey(
Match, Match,
@@ -95,12 +106,15 @@ class Tipp(models.Model):
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( client = models.ForeignKey(
Mandant, Mandant,
@@ -110,10 +124,12 @@ class Score(models.Model):
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):
class Chart(models.Model):
team = models.ForeignKey( team = models.ForeignKey(
Team, Team,
on_delete=models.CASCADE on_delete=models.CASCADE
@@ -128,7 +144,8 @@ class chart(models.Model):
class Meta: class Meta:
unique_together = ("team", "competition") unique_together = ("team", "competition")
class RelUserMandant(models.Model): class RelUserMandant(models.Model):
user = models.ForeignKey( user = models.ForeignKey(
User, User,
@@ -141,9 +158,11 @@ class RelUserMandant(models.Model):
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):
content = models.TextField() content = models.TextField()
published = models.BooleanField(default=True) published = models.BooleanField(default=True)
@@ -152,13 +171,14 @@ class Post(models.Model):
User, User,
on_delete=models.CASCADE on_delete=models.CASCADE
) )
class Meta: class Meta:
ordering = ['-created'] ordering = ['-created']
def __unicode__(self): def __unicode__(self):
return u'%s' % self.created return u'%s' % self.created
class RelPostMandant(models.Model): class RelPostMandant(models.Model):
post = models.ForeignKey( post = models.ForeignKey(
Post, Post,
@@ -171,6 +191,6 @@ class RelPostMandant(models.Model):
class Meta: class Meta:
unique_together = ("post", "mandant") unique_together = ("post", "mandant")
def __unicode__(self): def __unicode__(self):
return (str(self.post) + " -> " + str(self.mandant)) return (str(self.post) + " -> " + str(self.mandant))
+35 -46
View File
@@ -2,95 +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
import locale import locale
from suds.client import Client
import urllib.request
import urllib.error import urllib.error
import urllib.parse import urllib.parse
import psycopg2 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 = Client( try:
'http://www.openligadb.de/' if proxyurl is None:
+ 'Webservices/Sportsdata.asmx?WSDL') self.client = Client(wsdl=wsdl_url)
except (urllib.error.URLError): else:
self.error += "Connect to webservice failed." session = Session()
else: session.proxies = {'http': proxyurl, 'https': proxyurl}
try: transport = Transport(session=session)
t = suds.transport.http.HttpTransport() self.client = Client(wsdl=wsdl_url, transport=transport)
proxy = urllib.request.ProxyHandler({'http':proxyurl}) except (urllib.error.URLError, Exception) as e:
opener = urllib.request.build_opener(proxy) self.error += f"Connect to webservice failed: {str(e)}\n"
t.urlopener = opener
self.client = suds.client.Client(
'http://www.openligadb.de/Webservices/'
+ 'Sportsdata.asmx?WSDL', transport=t)
except urllib.error.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( return self.client.service.GetMatchdataByLeagueSaison(
leagueShortcut=league,leagueSaison=season) 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( return self.client.service.GetMatchdataByGroupLeagueSaison(
groupOrderID=matchdaynumber, groupOrderID=matchdaynumber,
leagueShortcut=league, leagueShortcut=league,
leagueSaison=season) leagueSaison=season)
)
def getTeams(self, season, league='bl1'): def getTeams(self, season, league='bl1'):
return(self.client.service.GetTeamsByLeagueSaison( return self.client.service.GetTeamsByLeagueSaison(
leagueShortcut=league, leagueShortcut=league,
leagueSaison=season) leagueSaison=season)
)
def getCurrentGroup(self, league): def getCurrentGroup(self, league):
return(self.client.service.GetCurrentGroup( return self.client.service.GetCurrentGroup(
leagueShortcut=league) leagueShortcut=league)
)
+1
View File
@@ -22,6 +22,7 @@ urlpatterns = [
re_path(r'^blog/newpost$', views.newBlogpost), re_path(r'^blog/newpost$', views.newBlogpost),
re_path(r'^blog/(?P<page>\d)$', views.blogindex), re_path(r'^blog/(?P<page>\d)$', views.blogindex),
re_path(r'^about$', views.about), 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/login/', auth_views.LoginView.as_view()),
re_path(r'^accounts/logout/', auth_views.LogoutView.as_view()) re_path(r'^accounts/logout/', auth_views.LogoutView.as_view())
] ]
+533 -395
View File
File diff suppressed because it is too large Load Diff