Initial commit

This commit is contained in:
2016-01-20 16:56:31 +01:00
commit 60d55652c0
26 changed files with 1668 additions and 0 deletions

60
templates/base.html Normal file
View File

@@ -0,0 +1,60 @@
{% load static %}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" dir="ltr">
<head>
<!-- meta tags -->
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="Author" content="Martin Bley" />
<meta name="Description" content="Tippspiel" />
<meta name="Copyright" content="Martin Bley, 2014-2015" />
<meta name="Robots" content="robots" />
<meta name="Generator" content="Django" />
<meta name="Keywords" content="Tippspiel Bundesliga" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap -->
<link href="{{ STATIC_URL }}css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap-Theme -->
<link href="{{ STATIC_URL }}css/bootstrap-theme.min.css" rel="stylesheet">
<!-- Bootstrap-Theme -->
<link href="{{ STATIC_URL }}css/tippy-bootstrap.css" rel="stylesheet">
<!-- 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 -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
{% block head %}{% endblock %}
</head>
<body>
<!-- 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>
<!-- 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>
{% block nav %}{% endblock %}
<div class="jumbotron">
</div>
<div class="container-fluid">
{% block body %}{% endblock %}
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-7">
<p>© Martin Bley, 2014-2015 | Dank an <a href="http://openligadb.de">OpenLigaDB</a> für
die Bereitstellung der Spielergebnisse.</p>
</div>
</div>
</div>
</body></html>

72
templates/blogindex.html Normal file
View File

@@ -0,0 +1,72 @@
{% extends "base.html" %}
{% load i18n static %}
{% load humanize %}
{% block head %}
<title> TipPy Blog</title>
{% 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>TipPy Blog</h2>
<p class="text-right">
<a class="btn btn-default" href="/blog/newpost" role="button">Neue Nachricht</a>
</p>
</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 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>
</div>
</div>
{% endfor %}
<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">&larr;</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">&rarr;</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
{% endblock %}

32
templates/blogpost.html Normal file
View File

@@ -0,0 +1,32 @@
{% extends "base.html" %}
{% block head %}
<title> TipPy Blog</title>
{% 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-8">
<article>
<header>
<h3> {{post.title}} </h3>
<p>
geposted am
<time datetime="{{post.created|date:""}}">
{{post.created|date}} von {{post.author}}
</time>
</p>
</header>
<p class="description">
{{post.description}}
</p>
{{post.content|safe}}
</article>
</div>
</div>
</div>
{% endblock %}

38
templates/charts.html Normal file
View File

@@ -0,0 +1,38 @@
{% extends "base.html" %}
{% block head %}
<title> TipPy Charts</title>
{% endblock %}
{% block nav %}
{% include "nav.html" with ls=ls season=season %}
{% endblock %}
{% block body %}
{% for mandant, users in mandant_dict.items %}
<div class="row">
<div class="col-md-6">
<h2>Bestenliste
{% if pos == 'rueck' %}
(Rückrunde)</h2>
<p><a href="/charts/{{ ls }}/{{ season }}/hin">Hinrunde anzeigen</a></p>
{% elif pos == 'hin' %}
(Hinrunde)</h3>
<p><a href="/charts/{{ ls }}/{{ season }}/rueck">Rückrunde anzeigen</a></p>
{% endif %}
<h4>Tippgemeinschaft: {{ mandant }}</h4>
<table class="table table-striped">
<tr>
<th>Spieler</th>
<th>Punkte</th>
</tr>
{% for user, score in users %}
<tr>
<td>{{ user }}</td>
<td>{{ score }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
{% endblock %}

33
templates/login.html Normal file
View File

@@ -0,0 +1,33 @@
{% 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 %}

109
templates/md.html Normal file
View File

@@ -0,0 +1,109 @@
{% extends "base.html" %}
{% load i18n static %}
{% load humanize %}
{% block head %}
<script type="text/javascript" src="{{ STATIC_URL }}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>Neueste Nachrichten</h2>
<p class="text-right">
<a class="btn btn-default" href="/blog/1" role="button">zum Blog</a>
</p>
{% for post, avatar in posts %}
<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 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 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">&larr;</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">&rarr;</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 %}

41
templates/nav.html Normal file
View File

@@ -0,0 +1,41 @@
{% load i18n static %}
<!-- Fixierte Navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Navigation ein-/ausblenden</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="navbar-brand">TipPy 1.0</span>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Tipps</a></li>
<li><a href="/charts/{{ ls }}/{{ season }}{% if pos %}/{{ pos }}{% endif %}">Bestenliste</a></li>
<li><a href="/blog/1">Blog</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if has_refresh %}
<li>
<a data-toggle="tooltip" title="Ergebnisse aktualisieren" href="/update/{{ ls }}/{{ season }}/{{ cur_md }}">
<span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
</a>
</li>
{% endif %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-user"></span> {{ user.first_name }} <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="/accounts/profile/{{user.id}}">Profil ändern</a></li>
<li><a href="/accounts/password_change/">Passwort ändern</a></li>
<li><a href="/logout">Abmelden</a></li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>

13
templates/nav_login.html Normal file
View File

@@ -0,0 +1,13 @@
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Navigation ein-/ausblenden</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="navbar-brand">TipPy 1.0</span>
</div>
</div>
</div>

View File

@@ -0,0 +1,49 @@
{% extends "base.html" %}
{% load i18n static %}
{% block head %}
<title> TipPy Blog</title>
{% endblock %}
{% block nav %}
{% include "nav.html" with ls=ls season=season %}
{% endblock %}
{% block body %}
<div id="content-main">
{% if form.errors %}
<div>
<p class="errornote">
{% if form.errors.items|length == 1 %}
{% trans "Please correct the error below." %}
{% else %}
{% trans "Please correct the errors below." %}
{% 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.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 %}

View File

@@ -0,0 +1,33 @@
{% 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 %}

View File

@@ -0,0 +1,22 @@
{% extends "base.html" %}
{% load i18n static %}
{% block title %}{% trans 'Password change successful' %}{% 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-5">
<h3>{% trans 'Password change successful' %}</h3>
<p>{% trans 'Your password was changed.' %}</p>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,59 @@
{% extends "base.html" %}
{% load i18n static %}
{% block title %}{% trans 'Password change' %}{% endblock %}
{% block nav %}
{% include "nav.html" with ls=ls season=season %}
{% endblock %}
{% block body %}
<div id="content-main">
<div>
{% if form.errors %}
<p class="errornote">
{% if form.errors.items|length == 1 %}
{% trans "Please correct the error below." %}
{% else %}
{% trans "Please correct the errors below." %}
{% endif %}</p>
{% endif %}
</div>
<div class="row">
<div class="col-md-5">
<h2 class="form-signin-heading">{% trans 'Password change' %}</h2>
<p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p>
<form class="form-horizontal" action="" method="post">{% csrf_token %}
<div class="form-group">
{{ form.old_password.errors }}
<label for="id_old_password" class="col-sm-4 control-label required">{% trans 'Old password' %}</label>
<div class="col-sm-5">
<input id="id_old_password" name="old_password" class="form-control" type="password" />
</div>
</div>
<div class="form-group">
{{ form.new_password1.errors }}
<label for="id_new_password1" class="col-sm-4 control-label required">{% trans 'New password' %}</label>
<div class="col-sm-5">
<input id="id_new_password1" name="new_password1" class="form-control" type="password" />
</div>
</div>
<div class="form-group">
{{ form.new_password2.errors }}
<label for="id_new_password2" class="col-sm-4 control-label required">{% trans 'Password (again)' %}</label>
<div class="col-sm-5">
<input id="id_new_password2" name="new_password2" class="form-control" type="password" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">{% trans 'Change my password' %}</button>
</div>
</div>
<script type="text/javascript">document.getElementById("id_old_password").focus();</script>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,80 @@
{% extends "base.html" %}
{% load i18n static %}
{% block title %}{% trans 'Password change' %}{% endblock %}
{% block nav %}
{% include "nav.html" with ls=ls season=season %}
{% endblock %}
{% block body %}
<div id="content-main">
<div>
{% if form.errors %}
<p class="errornote">
{% if form.errors.items|length == 1 %}
{% trans "Please correct the error below." %}
</p><p>{{ form.errors }}
{% else %}
{% trans "Please correct the errors below." %}
{% endif %}</p>
{% endif %}
</div>
<div class="row">
<div class="col-md-5">
<h2 class="form-signin-heading">{% trans 'Edit Profile' %}</h2>
{% if img %}
<p><img border="0" alt="Profile Pic" src="{{ img }}" /></p>
{% endif %}
<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">{% csrf_token %}
<div class="form-group">
<label for="{{ profile_form.avatar.id_for_label }}" class="col-sm-4 control-label required">Avatar</label>
<div class="col-sm-5">
{% if img %}
<img src="/media/{{ img }}" /><br />
<input id="avatar-clear_id" name="avatar-clear" type="checkbox" />
<label for="avatar-clear_id">Zurücksetzen</label><br />
Ändern: <input id="id_avatar" name="avatar" type="file" />
{% else %}
<input id="id_avatar" name="avatar" type="file" />
{% endif %}
</div>
</div>
<div class="form-group">
<label for="{{ user_form.first_name.id_for_label }}" class="col-sm-4 control-label required">Vorname</label>
<div class="col-sm-5">
{{ user_form.first_name }}
</div>
</div>
<div class="form-group">
<label for="{{ user_form.last_name.id_for_label }}" class="col-sm-4 control-label required">Nachname</label>
<div class="col-sm-5">
{{ user_form.last_name }}
</div>
</div>
<div class="form-group">
<label for="{{ user_form.email.id_for_label }}" class="col-sm-4 control-label required">E-Mail</label>
<div class="col-sm-5">
{{ user_form.email }}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">{% trans 'Update' %}</button>
</div>
</div>
</form>
</div>
</div>
{% if debug %}
<div class="row">
<div class="col-md-5">
<h2 class="form-signin-heading">{% trans 'Debug' %}</h2>
{% for line in debug %}
<p>{{ line }}</p>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endblock %}

View File

@@ -0,0 +1,22 @@
{% extends "base.html" %}
{% load i18n static %}
{% block title %}{% trans 'Profile change successful' %}{% 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-5">
<h3>{% trans 'Profile change successful' %}</h3>
<p>{% trans 'Your profile was changed.' %}</p>
</div>
</div>
</div>
{% endblock %}

0
tipp/__init__.py Normal file
View File

28
tipp/admin.py Normal file
View File

@@ -0,0 +1,28 @@
from tipp.models import Team, Match, Tipp, Score, Mandant, RelUserMandant, Competition, Post, UserProfile
from django.contrib import admin
class PostAdmin(admin.ModelAdmin):
# fields display on change list
list_display = ['title']
# fields to filter the change list with
list_filter = ['published', 'created']
# fields to search in change list
search_fields = ['title', 'content']
# enable the date drill down on change list
date_hierarchy = 'created'
# enable the save buttons on top on change form
save_on_top = True
# prepopulate the slug from the title - big timesaver!
prepopulated_fields = {"slug": ("title",)}
admin.site.register(Team)
admin.site.register(Match)
admin.site.register(Tipp)
admin.site.register(Mandant)
admin.site.register(Score)
admin.site.register(RelUserMandant)
admin.site.register(Competition)
admin.site.register(Post, PostAdmin)

40
tipp/forms.py Normal file
View File

@@ -0,0 +1,40 @@
from django import forms
from django.forms import ModelForm
from django.contrib.auth.models import User
from django.core.files.images import get_image_dimensions
from tipp.models import Match, Competition, Post, UserProfile
class NumberInput(forms.TextInput):
input_type = 'number'
class TippForm(forms.Form):
tippTeam1 = forms.IntegerField(required=True,widget=NumberInput(attrs={
'cols': '2',
'min': '0', 'max': '99', 'step': '1',
'class':'form-inline',
'role': 'form'}
))
tippTeam2 = forms.IntegerField(required=True,widget=NumberInput(attrs={
'cols': '2',
'min': '0', 'max': '99', 'step': '1',
'class':'form-inline',
'role': 'form'}
))
tippTeam1.widget.attrs['style'] = "width:35px"
tippTeam2.widget.attrs['style'] = "width:35px"
class BlogpostForm(ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['email', 'first_name', 'last_name']
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['avatar']

111
tipp/models.py Normal file
View File

@@ -0,0 +1,111 @@
from django.db import models
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
avatar = models.ImageField(upload_to="profiles/", blank=True)
def __unicode__(self):
return self.user.username
class Competition(models.Model):
leagueShortcut = models.CharField(max_length=32)
leagueName = models.CharField(max_length=128)
season = models.CharField(max_length=4)
def __unicode__(self):
return(self.leagueShortcut)
class Team(models.Model):
teamID = models.IntegerField(unique=True, primary_key=True)
name = models.CharField(max_length=200)
icon = models.FileField(upload_to="images/team_logos/")
abbr = models.CharField(max_length=3)
def __unicode__(self):
return self.name
class Match(models.Model):
matchID = models.IntegerField(unique=True,primary_key=True)
matchDateTime = models.DateTimeField()
group = models.IntegerField()
matchday = models.IntegerField()
idTeam1 = models.ForeignKey(Team, related_name='+')
idTeam2 = models.ForeignKey(Team, related_name='+')
pointsTeam1 = models.SmallIntegerField()
pointsTeam2 = models.SmallIntegerField()
finished = models.BooleanField()
season = models.CharField(max_length=4)
leagueShortcut = models.CharField(max_length=12)
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))
class Tipp(models.Model):
matchID = models.ForeignKey(Match)
tipperID = models.ForeignKey(User)
pointsTeam1 = models.PositiveSmallIntegerField()
pointsTeam2 = models.PositiveSmallIntegerField()
score = models.PositiveIntegerField(blank=True, null=True)
class Meta:
unique_together = ("matchID", "tipperID")
class Mandant(models.Model):
name = models.CharField(max_length=32, unique=True)
description = models.CharField(max_length=255)
def __unicode__(self):
return self.name
class Score(models.Model):
client = models.ForeignKey(Mandant)
exact_high = models.PositiveSmallIntegerField()
exact = models.PositiveSmallIntegerField()
diff = models.PositiveSmallIntegerField()
tendency = models.PositiveSmallIntegerField()
def __unicode__(self):
return str(self.client)
class chart(models.Model):
team = models.ForeignKey(Team)
competition = models.ForeignKey(Competition)
points = models.PositiveSmallIntegerField()
diff = models.SmallIntegerField()
games = models.PositiveSmallIntegerField()
class Meta:
unique_together = ("team", "competition")
class RelUserMandant(models.Model):
user = models.ForeignKey(User)
mandant = models.ForeignKey(Mandant)
class Meta:
unique_together = ("user", "mandant")
def __unicode__(self):
return (str(self.user) + " -> " + str(self.mandant))
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
published = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s' % self.title
def get_absolute_url(self):
return reverse('tipp.views.blogpost', args=[self.slug])

68
tipp/openliga.py Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python
#
# Copyright 2013 by Martin Bley <martin@mb-oss.de>
#
# tippy.py is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# tippy.py is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with tippy.py. If not, see <http://www.gnu.org/licenses/>.
#
import sys, locale, suds, urllib2, psycopg2
class OpenLiga(object):
version = "0.1"
error = ""
proxyurl = None
debug = None
client = None
def __init__(self, proxyurl=None, debug=False):
# set locale to environment (for dispaying localized dates)
locale.setlocale(locale.LC_TIME, "")
self.debug = debug
# get a SUDS client object
if self.proxyurl is None:
try:
self.client = suds.client.Client('http://www.openligadb.de/Webservices/Sportsdata.asmx?WSDL')
except (urllib2.URLError):
self.error += "Connect to webservice failed."
else:
try:
t = suds.transport.http.HttpTransport()
proxy = urllib2.ProxyHandler({'http':proxyurl})
opener = urllib2.build_opener(proxy)
t.urlopener = opener
self.client = suds.client.Client('http://www.openligadb.de/Webservices/Sportsdata.asmx?WSDL', transport=t)
except urllib2.URLError as e:
self.error += "Connect to webservice failed (via proxy " + proxyurl + "): " + str(e) + "\n"
def getSeason(self, season, league='bl1'):
""" Get the whole season.
Args: season and league shortcut (optional)
"""
return(self.client.service.GetMatchdataByLeagueSaison(leagueShortcut=league,leagueSaison=season))
def getMatchday(self, season, matchdaynumber, league='bl1'):
""" Get matchday.
Args: season, matchdaynumber and league shortcut (optional)
"""
return(self.client.service.GetMatchdataByGroupLeagueSaison(groupOrderID=matchdaynumber,leagueShortcut=league,leagueSaison=season))
def getTeams(self, season, league='bl1'):
return(self.client.service.GetTeamsByLeagueSaison(leagueShortcut=league,leagueSaison=season))

16
tipp/tests.py Normal file
View File

@@ -0,0 +1,16 @@
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)

3
tipp/updateMatch.py Normal file
View File

@@ -0,0 +1,3 @@
from tipp.models import Match

486
tipp/views.py Normal file
View File

@@ -0,0 +1,486 @@
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from django.shortcuts import render_to_response, redirect, render, get_object_or_404
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import password_reset, password_reset_confirm
from django.core.context_processors import csrf
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, InvalidPage, EmptyPage, PageNotAnInteger
from django.utils import timezone
from django.utils.text import slugify
from django.db.models import Sum
from django.conf import settings
from os.path import join as pjoin
from tipp.models import *
from tipp.forms import *
from openliga import *
from datetime import datetime
from PIL import Image as PImage
import urllib2, pytz, os
timezoneLocal = pytz.timezone('Europe/Berlin')
@login_required
def home(request):
ls = get_current_ls()
season = get_current_season()
return redirect("matchday",
ls = ls,
season = season,
matchday=str(get_current_md(ls, season)).zfill(2)
)
@login_required
def profile(request, pk):
user = User.objects.get(id=pk)
profile, created = UserProfile.objects.get_or_create(user=user)
if profile.avatar:
img = profile.avatar.name
else:
img = None
debug = []
debug.append('avatar: ' + str(img))
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information.
# Note that we make use of both UserForm and UserProfileForm.
user_form = UserForm(data=request.POST, instance=user)
profile_form = UserProfileForm(data=request.POST, instance=profile)
# If the two forms are valid...
if user_form.is_valid() and profile_form.is_valid():
# Save the user's form data to the database.
user = user_form.save()
# Now sort out the UserProfile instance.
# Since we need to set the user attribute ourselves, we set commit=False.
# This delays saving the model until we're ready to avoid integrity problems.
profile = profile_form.save(commit=False)
profile.user = user
# Did the user provide a profile picture?
# If so, we need to get it from the input form and put it in the UserProfile model.
if 'avatar' in request.FILES:
profile.avatar = request.FILES['avatar']
# Now we save the UserProfile model instance.
profile.save()
# create thumbnail
imfn = pjoin(settings.MEDIA_ROOT, profile.avatar.name)
im = PImage.open(imfn)
im.thumbnail((50,50), PImage.ANTIALIAS)
im.save(settings.MEDIA_ROOT + profile.avatar.name)
if 'avatar-clear' in request.POST:
if 'on' in request.POST['avatar-clear']:
image = pjoin(settings.MEDIA_ROOT, img)
debug.append('Is the image ' + str(image) + ' a regular file? ' + str(os.path.isfile(image)))
if os.path.isfile(image):
os.remove(image)
profile.save()
for item in request.POST:
debug.append(str(item) + " -> " + str(request.POST[item]))
# Invalid form or forms - mistakes or something else?
# Print problems to the terminal.
# They'll also be shown to the user.
else:
print user_form.errors, profile_form.errors
return redirect( '/accounts/profile/' + str(user.id) )
# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
user_form = UserForm(
initial={ 'last_name': user.last_name,
'first_name': user.first_name,
'email': user.email },
instance=user
)
profile_form = UserProfileForm(instance=profile)
return render(request, 'registration/profile.html', {
'user_form': user_form,
'profile_form': profile_form,
'debug': debug,
'img': img}
)
@login_required
def update(request, ls, season, cur_md):
"""
To do:
- update table tipp_competition
"""
ol = OpenLiga()
md_matches = ol.getMatchday(str(season), int(cur_md) ,ls)
# Achtung: DateTimeField prüfen
for match in md_matches[0]:
# Endergebnis holen
matchResults = match['matchResults']
try:
for result in matchResults[0]:
if result['resultName'] == "Endergebnis":
pointsTeam1=int(result['pointsTeam1'])
pointsTeam2=int(result['pointsTeam2'])
elif result['resultName'] == "Halbzeitergebnis":
pointsTeam1=int(result['pointsTeam1'])
pointsTeam2=int(result['pointsTeam2'])
except:
pointsTeam1=-1
pointsTeam2=-1
m = Match(matchID=unicode(match['matchID']),
matchDateTime=datetime.strptime(unicode(match['matchDateTime']), '%Y-%m-%d %H:%M:%S'),
group=int(match['groupID']),
matchday=int(match['groupOrderID']),
idTeam1=Team.objects.get(teamID=int(match['idTeam1'])),
idTeam2=Team.objects.get(teamID=int(match['idTeam2'])),
pointsTeam1=pointsTeam1,
pointsTeam2=pointsTeam2,
finished=bool(match['matchIsFinished']),
season=match['leagueSaison'],
leagueShortcut=match['leagueShortcut']
)
m.save()
pointsTeam1=-1
pointsTeam2=-1
""" evaluate scores """
scores = Score.objects.get(client=Mandant.objects.get(name='huse'))
finished_matches=Match.objects.filter(finished=True)
for match in finished_matches:
tipps = Tipp.objects.filter(matchID=match.matchID)
for tipp in tipps:
score = 0
goals_total = match.pointsTeam1 + match.pointsTeam2
""" Tipp is acurate """
if (tipp.pointsTeam1 == match.pointsTeam1 and tipp.pointsTeam2 == match.pointsTeam2):
if goals_total >= 5:
score = scores.exact_high
else:
score = scores.exact
tipp.score = score
tipp.save()
continue
""" who won? """
winnerReal = None
if match.pointsTeam1 > match.pointsTeam2:
winnerReal = 1
elif (match.pointsTeam2 > match.pointsTeam1):
winnerReal = 2
elif (match.pointsTeam1 == match.pointsTeam2):
winnerReal = 0
winnerTipp = None
if tipp.pointsTeam1 > tipp.pointsTeam2:
winnerTipp = 1
elif (tipp.pointsTeam2 > tipp.pointsTeam1):
winnerTipp = 2
elif (tipp.pointsTeam1 == tipp.pointsTeam2):
winnerTipp = 0
diffReal = match.pointsTeam1 - match.pointsTeam2
diffTipp = tipp.pointsTeam1 - tipp.pointsTeam2
if ( winnerTipp == winnerReal ):
if ( diffTipp == diffReal ):
score = scores.diff
else:
score = scores.tendency
tipp.score = score
tipp.save()
continue
tipp.score = score
tipp.save()
continue
return redirect("matchday", ls=ls, season=season, matchday=cur_md)
@login_required
def matchday(request, ls, season, matchday, template_name='md.html'):
debug = ''
debug += "Debugging: "
has_refresh = True
""" get matchday closest to current date """
md_matches = Match.objects.filter(leagueShortcut=ls, season=season, matchday=int(matchday)).order_by('matchDateTime')
""" get the current user """
user = User.objects.get(username=request.user.username)
""" get mandants current user is related """
mandants = RelUserMandant.objects.filter(user=request.user).values_list('mandant', flat=True)
""" get mates """
tipp_mates = []
for m in mandants:
rs = RelUserMandant.objects.filter(mandant=m)
for r in rs:
tipp_mates.append({
'mate': r.user,
'tipps': [],
'sum_score': 0
})
matches = []
for match in md_matches:
"""
create a form for each tipp
"""
form = TippForm(request.POST or None, prefix=str(match.matchID))
"""
check if Tipp already exists
"""
try:
tipp = Tipp.objects.get(tipperID=user.id,matchID=match.matchID)
except ObjectDoesNotExist:
tipp = None
"""
if request is a POST, process form data, else just show form
"""
if form.is_valid():
data = form.cleaned_data
if tipp is not None:
""" Tipp exists an needs an UPDATE"""
tipp = Tipp(id=tipp.pk,
matchID=match,
tipperID=user,
pointsTeam1=data['tippTeam1'],
pointsTeam2=data['tippTeam2']
)
tipp.save()
else:
""" do INSERT """
tipp = Tipp( matchID=match,
tipperID=user,
pointsTeam1=data['tippTeam1'],
pointsTeam2=data['tippTeam2'])
tipp.save()
match_started = timezone.now() >= match.matchDateTime
if tipp is not None:
f = TippForm(prefix=str(match.matchID),
initial={'tippTeam1': tipp.pointsTeam1, 'tippTeam2': tipp.pointsTeam2}
)
else:
f = TippForm(prefix=str(match.matchID))
item = {}
item['matchDateTime'] = (match.matchDateTime.astimezone(timezoneLocal).strftime('%a %d.%m, %H:%M'))
item['iconTeam1']= str(match.idTeam1.icon)
item['nameTeam1']= str(match.idTeam1)
item['abbrTeam1']= str(match.idTeam1.abbr)
item['iconTeam2'] = str(match.idTeam2.icon)
item['nameTeam2'] = str(match.idTeam2)
item['abbrTeam2']= str(match.idTeam2.abbr)
item['started'] = match_started
item['finished'] = match.finished
if (match.pointsTeam1 == -1 or match.pointsTeam2 == -1):
item['matchResult'] = "-:-"
else:
item['matchResult'] = str(match.pointsTeam1) + ":" + str(match.pointsTeam2)
item['tippFormTeam1'] = f['tippTeam1']
item['tippFormTeam2'] = f['tippTeam2']
if match_started is True:
f.fields['tippTeam1'].widget.attrs['disabled'] = True
f.fields['tippTeam2'].widget.attrs['disabled'] = True
for mate in tipp_mates:
try:
matetipp = Tipp.objects.get(tipperID=mate['mate'],matchID=match.matchID)
if match_started is True:
mate['tipps'].append(str(matetipp.pointsTeam1) + ":" + str(matetipp.pointsTeam2) + "(" + str(matetipp.score) + ")")
if match.finished is True:
mate['sum_score'] += matetipp.score
else:
mate['tipps'].append(u'\u2714')
except Exception as e:
mate['tipps'].append(u'\u2717')
matches.append(item)
# get the newest blogposts
posts = []
for post in Post.objects.filter(published=True)[:2]:
try:
avatar = UserProfile.objects.get(user_id=post.author_id).avatar.name
except:
avatar = None
posts.append( (post, avatar) )
return render(request, 'md.html', {
#'debug': debug,
#'mds_season': mds_in_season,
'cur_md': matchday,
'matches': matches,
'ls': ls,
'season': season,
'username': user,
'tipp_mates': sorted(tipp_mates, key=lambda k: k['sum_score'], reverse=True),
'posts': posts,
'has_refresh': has_refresh
})
@login_required
def charts(request, ls, season, pos='default', template_name='charts.html'):
debug = ''
if pos == 'default':
if get_current_md(ls, season) < 18:
pos = 'hin'
matches = Match.objects.filter(leagueShortcut=ls, season=season, matchday__lte=17)
else:
pos = 'rueck'
matches = Match.objects.filter(leagueShortcut=ls, season=season, matchday__gte=18)
elif pos == 'hin':
matches = Match.objects.filter(leagueShortcut=ls, season=season, matchday__lte=17)
elif pos == 'rueck':
matches = Match.objects.filter(leagueShortcut=ls, season=season, matchday__gte=18)
else:
matches = Match.objects.filter(leagueShortcut=ls, season=season)
# get mandants of current user
mandants = RelUserMandant.objects.filter(user=request.user).values_list('mandant', flat=True)
# main loop
mandant_dict = {}
for m in mandants:
mandant = Mandant.objects.get(id=m)
# get users
users = RelUserMandant.objects.filter(mandant=m).values_list('user', flat=True)
user_dict = {}
for userid in users:
# get user object, then fetch matches for user
user = User.objects.get(id=userid)
score = Tipp.objects.filter(matchID__in=matches, tipperID=user).aggregate(Sum('score'))
user_dict[user.first_name] = score['score__sum']
mandant_dict[mandant.name] = sorted(user_dict.items(), key=lambda x: x[1], reverse=True)
return render(request, template_name, {
#'debug': debug,
'mandant_dict': mandant_dict,
'season': season,
'ls': ls,
'pos': pos
})
@login_required
def blogindex(request, page):
# get the blog posts that are published
post_list = []
for post in Post.objects.filter(published=True):
try:
avatar = UserProfile.objects.get(user_id=post.author_id).avatar.name
except:
avatar = None
post_list.append( (post, avatar) )
p = Paginator(post_list, 5)
try:
posts = p.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
posts = p.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
posts = p.page(p.num_pages)
# now return the rendered template
return render(request, 'blogindex.html', {
'posts': posts,
'ls': get_current_ls(),
'season': get_current_season(),
'page': page
})
@login_required
def blogpost(request, slug):
# get the Post object
post = get_object_or_404(Post, slug=slug)
# now return the rendered template
return render(request, 'blogpost.html', {
'post': post,
'ls': get_current_ls(),
'season': get_current_season()
})
@login_required
def newBlogpost(request):
"""
if this is a POST request we need to process the form data
"""
if request.method == 'POST':
# create form instance and populate it with data from the request
form = BlogpostForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data
data = form.cleaned_data
slug = slugify(data['title'])
p = Post(author_id=request.user.id, slug=slug, title=data['title'], content=data['content'])
p.save()
# ...
# redirect to a new URL:
return redirect( '/blog/1')
# if a GET (or any other method) we'll create a blank form
else:
blogpostForm = BlogpostForm()
return render(request, 'newblogpost.html', {
'form': blogpostForm,
'ls': get_current_ls(),
'season': get_current_season()
})
def logout(request):
"""
Log users out and re-direct them to the main page.
"""
logout(request)
return HttpResponseRedirect('/')
def get_current_md(ls,season):
""" get current matchday """
current_md = Match.objects.filter(leagueShortcut=ls, season=season, finished=False).order_by('matchday').values_list('matchday', flat=True).distinct()[0]
return(current_md)
def get_current_ls():
return("bl1")
def get_current_season():
return("2015")

0
tippy/__init__.py Normal file
View File

188
tippy/settings.py Normal file
View File

@@ -0,0 +1,188 @@
"""
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 = '/opt/TipPy/TipPy/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/')
# 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.
#'/opt/TipPy/TipPy/tipp/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&amp;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'

37
tippy/urls.py Normal file
View File

@@ -0,0 +1,37 @@
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,
}),
)

28
tippy/wsgi.py Normal file
View File

@@ -0,0 +1,28 @@
"""
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)