neue Verzeichnissstruktur

This commit is contained in:
Christian Berg
2014-11-26 13:13:07 +01:00
parent daa35f5913
commit f34281089d
3372 changed files with 168 additions and 2544 deletions

1
membership/__init__.py Normal file
View File

@@ -0,0 +1 @@
PAID_MEMBERSHIP_GROUP = 2

62
membership/admin.py Normal file
View File

@@ -0,0 +1,62 @@
'''
Created on 19.09.2011
@author: christian
'''
# import stuff we need from django
from django.contrib import admin
from membership.models import Membership, ActivationRequest
from django.utils.translation import ugettext as _
from imagekit.admin import AdminThumbnail
def activate_user(modeladmin, request, queryset):
for activation in queryset:
membership = Membership.objects.get(username=activation.user.username)
membership.save()
activation.activate()
activate_user.short_description = _('Activate selected User')
def cleanup_activation(modeladmin, request, queryset):
for activation in queryset:
if activation.expired:
activation.user.delete()
cleanup_activation.short_description = _("Cleanup selected Activation Requests")
class MembershipAdmin(admin.ModelAdmin):
admin_thumbnail = AdminThumbnail(image_field='thumbnail')
list_filter = ('membership', 'confirmed')
list_display = (
'admin_thumbnail',
'nickname',
'first_name',
'last_name',
'membership',
'confirmed',
'paid_until',
)
list_editable = ('confirmed', 'paid_until',)
list_display_links = ('nickname',)
fieldsets = ((None, {
'fields': ('gender', ('first_name', 'last_name'), ('email', 'website'))
}),
(_('Membership'), {
'classes': ('collapse',),
'fields': (('membership', 'confirmed'), 'birthday', 'telephone',
'street_name', ('post_code', 'city'))
}),
)
ordering = ('nickname',)
search_fields = ('nickname', 'first_name', 'last_name',)
admin.site.register(Membership, MembershipAdmin)
class RegistrationAdmin(admin.ModelAdmin):
list_display = ('username', 'first_name', 'last_name', 'email',
'registration_date', 'expired')
search_fields = ('user__username', 'user__first_name')
actions = [cleanup_activation, activate_user]
admin.site.register(ActivationRequest, RegistrationAdmin)

146
membership/forms.py Normal file
View File

@@ -0,0 +1,146 @@
'''
Created on 03.10.2011
@author: Christian
'''
from . import models
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.utils.translation import ugettext_lazy as _
from utils.html5 import forms
from utils.massmailer import MassMailer
class MembershipForm(forms.ModelForm):
error_css_class = 'error'
required_css_class = 'required'
birthday = forms.DateField(label=_('birthday'), required=False)
class Meta:
model = models.Membership
fields = (
'nickname', 'gender', 'first_name', 'last_name', 'email', 'avatar',
'website', 'membership', 'birthday', 'telephone', 'street_name',
'post_code', 'city', 'comment'
)
def clean_birthday(self):
if self.cleaned_data['membership'] \
and not self.cleaned_data['birthday']:
raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.'))
return self.cleaned_data['birthday']
def clean_telephone(self):
if self.cleaned_data['membership'] \
and not self.cleaned_data['telephone']:
raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.'))
return self.cleaned_data['telephone']
def clean_street_name(self):
if self.cleaned_data['membership'] \
and not self.cleaned_data['street_name']:
raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.'))
return self.cleaned_data['street_name']
def clean_post_code(self):
if self.cleaned_data['membership'] \
and not self.cleaned_data['post_code']:
raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.'))
return self.cleaned_data['post_code']
def clean_city(self):
if self.cleaned_data['membership'] and not self.cleaned_data['city']:
raise forms.ValidationError(_('For your membership, we need this. \
Please fill out this field yet.'))
return self.cleaned_data['city']
class RegistrationForm(forms.ModelForm):
"""
Form to register a new user account.
Validates that the requested username and email is not already in use,
requires the password to be entered twice to catch typos.
sends an activation request per mail, to validate the eMail.
"""
error_css_class = 'error'
required_css_class = 'required'
first_name = forms.CharField(max_length=30, required=True,
label=_('Given Name'))
last_name = forms.CharField(max_length=30, required=True,
label=_('Last Name'))
username = forms.SlugField(required=True, max_length=30,
label=_('Username'),
help_text=_("The Username can only contain the letters from A to Z, \
Numbers, and the underscore. It must be at least 2 characters long, \
and cannot be longer the 30. The first character must be a letter."))
email = forms.EmailField(required=True)
password1 = forms.CharField(widget=forms.PasswordInput(),
label=_('password'))
password2 = forms.CharField(widget=forms.PasswordInput(),
label=_('password (again)'))
recaptcha = forms.ReCaptchaField()
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'email',)
def clean_username(self):
'''
Validate that the username is not already in use.
'''
try:
User.objects.get(username__iexact=self.cleaned_data['username'])
except User.DoesNotExist:
return self.cleaned_data['username']
raise forms.ValidationError(_(u'This username is already taken. \
Please choose another.'))
def clean_email(self):
'''
Validate that the supplied email address is unique for the site.
'''
if User.objects.filter(email__iexact=self.cleaned_data['email']):
raise forms.ValidationError(_(u'This email address is already in \
use. Please supply a different email address.'))
return self.cleaned_data['email']
def clean_password2(self):
password1 = self.cleaned_data.get("password1", "")
password2 = self.cleaned_data["password2"]
if password1 != password2:
raise forms.ValidationError(
_("The two password fields didn't match."))
return password2
def send_email(self, activation):
mailer = MassMailer()
mailer.subject = 'Deine Anmeldung auf %s' % Site.objects.get_current()
mailer.txt_template = 'membership/email/activation_email.txt'
mailer.context = {
'user': activation.user,
'site': Site.objects.get_current(),
'activation_key': activation.activation_key,
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
}
mailer.add_recipient(activation.user)
mailer.send()
def save(self, commit=True):
"""
Creates the new ``User`` and ``RegistrationProfile`` and
returns the ``User``.
"""
user = super(RegistrationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.is_active = False
if commit:
user.save()
activation = models.ActivationRequest.objects.create_pending_registration(user)
self.send_email(activation)
return user

View File

@@ -0,0 +1 @@
#!/usr/bin/python

View File

@@ -0,0 +1 @@
#!/usr/bin/python

View File

@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils.translation import ugettext_lazy as _
from membership.models import ActivationRequest
class Command(BaseCommand):
help = "Delete all expired user registrations from the database"
def handle(self, *args, **options):
for activation in ActivationRequest.objects.expired():
activation.user.delete()

View File

@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
"""
When you get an error email from your Django app telling you someone got a
server error,
its not always easy to tell which user had a problem.
It might help your debugging to know or you might want to contact the user to
tell them you have fixed the problem.
"""
from django.contrib.auth.models import User
from django.contrib.sessions.models import Session
from django.core.management.base import BaseCommand, CommandError
from django.utils.translation import ugettext_lazy as _
from optparse import make_option
class Command(BaseCommand):
args = '<session_key session_key ...>'
help = 'If the session still exists find it and show the related User'
option_list = BaseCommand.option_list + (
make_option('--delete',
action='store_true',
dest='delete',
default=False,
help='Delete the Useraccount'),
make_option('--ban',
action='store_true',
dest='ban',
default=False,
help='Ban the Useraccount'),
)
def handle(self, *args, **options):
for session_key in args:
try:
session = Session.objects.get(session_key=session_key)
uid = session.get_decoded().get('_auth_user_id')
user = User.objects.get(pk=uid)
except Session.DoesNotExist:
self.stderr.write('Session "%s" does not exist' % session_key)
continue
except User.DoesNotExist:
self.stderr.write('Session "%s" has no registed User' % session_key)
continue
if options['delete']:
self.stdout.write('deleting %s'% user.username)
user.delete()
elif options['ban']:
self.stdout.write('banning %s' % user.username)
user.is_active = False
user.save()
else:
self.stdout.write("Username: %s" % user.username)

277
membership/models.py Normal file
View File

@@ -0,0 +1,277 @@
# -*- encoding: utf-8 -*-
from . import PAID_MEMBERSHIP_GROUP
from datetime import timedelta
from django.utils import timezone
from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import FieldError
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext as _
from imagekit.models import ImageSpecField
from imagekit.processors import SmartResize
from os import path
from utils import OverwriteStorage
import random
import hashlib
GENDER_CHOICES = (
('m', _('Male')),
('f', _('Female')),
)
def get_upload_path(instance, filename):
'''
Erstellt den Pfad und Dateinamen für den Upload dynmisch.
@param instance: The Membership Object for the uploaded image
@param filename: the filename of the uploaded image
'''
extension = path.splitext(filename)[1]
return 'membership/%s%s' % (instance.user.username, extension)
class ActivationManager(models.Manager):
'''
Manages pending user registrations
'''
def activate(self, activation_key):
'''
searches the pending registrations for the given activation key.
Set the corresponding user to active, if the key was found
and the key has not expired yet.s
@param activation_key: the key found in the activation email
'''
try:
activation_request = self.get(activation_key=activation_key)
if activation_request.expired():
activation_request.user.delete()
activation_request.delete()
return False
elif not activation_request.user.is_active:
activation_request.user.is_active = True
activation_request.user.save()
activation_request.delete()
return activation_request.user
except self.model.DoesNotExist:
return False
def create_pending_registration(self, user):
'''
creates a PendingActivation instance with an random activation key.
@param user: the user that requests activation.
'''
salt = str(random.random())
activation_key = hashlib.sha1(salt + user.username).hexdigest()
return self.create(user=user, activation_key=activation_key)
def expired(self):
return self.filter(
user__is_active=False,
user__date_joined__lt=self.expiration_date
)
class ActivationRequest(models.Model):
'''
Each ActivationRequest contains an activation key and an user.
The key will be send by email to the user
if the user clicks on the link he can activate his in_active account.
'''
user = models.ForeignKey(User, unique=True, verbose_name=_('user'))
activation_key = models.CharField(_('activation key'), max_length=40)
objects = ActivationManager()
class Meta:
verbose_name = _('pending activation')
verbose_name_plural = _('pending activations')
def __unicode__(self):
return _("user registration for %s") % self.user
def activate(self):
self.user.is_active = True
self.user.save()
self.delete()
@property
def expiration_date(self):
timespan = timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
return self.user.date_joined + timespan
@property
def email(self):
return self.user.email
def expired(self):
if self.user.is_active:
return False
elif timezone.now() >= self.expiration_date:
return True
else:
return False
expired.boolean = True
@property
def first_name(self):
return self.user.first_name
@property
def last_name(self):
return self.user.last_name
@property
def registration_date(self):
return self.user.date_joined
@property
def username(self):
return self.user.username
class MembershipManager(models.Manager):
def get(self, *args, **kwargs):
'''
First try's to fetch the requested Membership Object from the Database,
if the requestetd Membership does not Exists (yet) try to fetch the
corresponding User, and create the Membership with the filled in
Userdata.
'''
try:
if 'username' in kwargs:
return models.Manager.get(self,
user__username=kwargs['username']
)
else:
return models.Manager.get(self, *args, **kwargs)
except FieldError:
user = User.objects.get(*args, **kwargs)
except Membership.DoesNotExist:
if 'user' in kwargs:
user = User.objects.get(pk=kwargs['user'].id)
else:
user = User.objects.get(*args, **kwargs)
membership = Membership(
user=user,
nickname=user.username,
first_name=user.first_name,
last_name=user.last_name,
email=user.email
)
return membership
class Membership(models.Model):
user = models.OneToOneField(User)
nickname = models.SlugField(_('Nickname'), unique=True)
gender = models.CharField(
_("Gender"),
max_length=1,
choices=GENDER_CHOICES
)
first_name = models.CharField(_("Given Name"), max_length=30)
last_name = models.CharField(_("Last Name"), max_length=30)
email = models.EmailField(_('Email'), unique=True)
website = models.URLField(blank=True)
avatar = models.ImageField(
upload_to=get_upload_path,
storage=OverwriteStorage(),
blank=True,
null=True
)
membership = models.BooleanField(_('Membership'),
default=False,
help_text=_('Yes, I confirm that I am in agreement with the statutes \
and would like to become a member.')
)
birthday = models.DateField(_("Birthday Date"), blank=True, null=True)
telephone = models.CharField(_("Telephone"),
max_length=30,
blank=True,
null=True
)
street_name = models.CharField(_("Address"),
max_length=75,
blank=True,
null=True
)
post_code = models.PositiveSmallIntegerField(_("Postcode"),
blank=True,
null=True
)
city = models.CharField(_("Town/City"),
max_length=75,
blank=True,
null=True
)
deposit = models.PositiveSmallIntegerField(default=0, editable=False)
registration_date = models.DateField(auto_now_add=True, editable=False)
paid_until = models.DateField(_('Paid until'),
blank=True,
null=True,
editable=True
)
confirmed = models.BooleanField(_('Confirmed'),
default=False,
help_text=_('This person has paid the membership fee.')
)
comment = models.TextField(blank=True)
objects = MembershipManager()
thumbnail = ImageSpecField(
processors=[SmartResize(width=60, height=60)],
format='PNG',
source='avatar',
)
profile = ImageSpecField(
processors=[SmartResize(width=140, height=140)],
format='PNG',
source='avatar',
)
class Meta(object):
ordering = ('last_name', 'first_name',)
verbose_name = _('Membership')
verbose_name_plural = _('Memberships')
def __unicode__(self):
return _('Userprofile for %s' % self.user.username)
def clean(self):
# Update the Profile Info from the User Object
if not self.nickname:
self.nickname = self.user.username
if not self.first_name:
self.first_name = self.user.first_name
if not self.last_name:
self.last_name = self.user.last_name
if not self.email:
self.email = self.user.email
def get_absolute_url(self):
return reverse('membership-details',
kwargs={'username': self.user.username}
)
def save(self, *args, **kwargs):
super(Membership, self).save(*args, **kwargs)
self.user.username = self.nickname
self.user.first_name = self.first_name
self.user.last_name = self.last_name
self.user.email = self.email
if self.confirmed:
self.user.groups.add(PAID_MEMBERSHIP_GROUP)
else:
self.user.groups.remove(PAID_MEMBERSHIP_GROUP)
self.user.save()

21
membership/specs.py Normal file
View File

@@ -0,0 +1,21 @@
from imagekit.specs import ImageSpec
from imagekit import processors
class ResizeThumbnail(processors.Resize):
width = 60
height = 60
crop = True
class ResizeProfile(processors.Resize):
width = 140
height = 140
crop = True
class Thumbnail(ImageSpec):
pre_cache = True
processors = (ResizeThumbnail,)
class Profile(ImageSpec):
pre_cache = False
processors = (ResizeProfile,)

View File

@@ -0,0 +1,16 @@
{% extends "base.html" %}
{% load i18n %}
{% block title %}Account aktivierung fehlgeschlagen{% endblock %}
{% block maincontent %}
<h2 class="grid_12">Aktivierung fehlgeschlagen</h2>
<p class="grid_12">Leider war die Aktivierung des Schlüssels &ldquo;{{ activation_key }}&rdquo; war nicht erfolgreich, dies könnte mehrere Gründe haben:</p>
<img class="grid_4" src="" alt="" />
<ul class="grid_8">
<li><strong>Der Aktivierungs Link ist nicht korrekt.</strong> Bitte kopiere die ganze Zeile aus der E-Mail in die Adressleiste.</li>
<li><strong>Der Aktivierungs Schlüssel ist abgelaufen.</strong> Dieser ist nur {{ expiration_days }} Tage gültig.In diesem Fall fülle das <a href="{% url 'membership-register' %}">Registrierungs Formular</a> bitte erneut aus.</p></li>
<li><strong>Der Account wurde schon aktiviert.</strong> Dies passiert sehr schnell, veruche zuerst dich mit deinen Daten <a href="{% url 'login' %}">anzumelden</a>. Sollte das nicht funktionieren, kannst du dir ja mal <a href="{% url 'password_reset' %}">neue Zugangsdaten zuschicken</a> lassen.</li>
<li><strong>Ein obskurer Fehler ist aufgetreten.</strong> In diesem Fall, nimm bitte Kontakt mit dem Webadmin auf.</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends "base.html" %}
{% block title %}Bestätigungs E-Mail wurde abgeschickt{% endblock %}
{% block content %}
<div class="left_column">
<h2>Bestätigungs E-Mail wurde abgeschickt</h2>
<p>Danke für die Anmeldung! Um sicher zu gehen das die angegebene E-Mail Adresse korrekt ist,
wurde eine <em>Aktivierungs E-Mail</em> an deinen Adresse geschickt.Diese enthält einen Link, der deinen Benutzer Account frei schaltet.</p>
<p>Solltest du <em>keine</em> Bestätigung bekommen haben, oder deine Mail Adresse <em>falsch</em> sein.
Setze dich bitte mit den Webadministrator in Kontakt. Dieser kann bei deinem Anliegen helfen.</p>
<p class="more"><a href="mailto:webmaster@animanga.at">E-Mail an den Webmaster</a></p>
</div>
<div class="right_column">
<h2>E-Mail nicht angekommen?</h2>
<ul>
<li><p>Einige Anti-Spam Techniken verzögern den Empfang von E-Mails.
Bei solchen Postfächern kann der <strong>Empfang</strong> einzelner Mails <strong>bis zu 30 Minuten</strong> dauern.</p></li>
<li><p>Bitte überprüfe den <em>"Junk"</em> bzw. <em>"SPAM"</em> Ordner deines Postfaches.
Automatisch generierte E-Mails werden leider sehr oft falsch von SPAM-Filtern geschluckt</p></li>
<li><p>Bitte Überprüfe die Richigkeit deiner angegebenen <strong>E-Mail Adresse</strong>.</p></li>
</ul>
</div>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block title %}Aktivierung erfolgreich{% endblock %}
{% block maincontent %}
<h2 class="grid_12">Aktivierung erfolgreich</h2>
<p class="grid_7">Du kannst dich absofort jeder Zeit
<a href="/accounts/login/">anmelden</a> und deinen Acount zu Nutzen.<br/>
Viel Spaß auf der Seite!</p>
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends "email.html" %}
{% block body %}
<h2>Herzlich Willkommen {{user}}!</h2>
<p>Jemand (hoffentlich du selbst) möchte mit dieser E-Mail Adresse einen neuen
Benutzer Account für {{site}} anlegen.</p>
<p>Solltest du diesen Account aktivieren wollen, klicke bitte auf den unten
stehenden Link, oder kopiere diesen in die Adresszeile deines Browsers:</p>
<ul>
<li><a href="http://{{site.domain}}/accounts/activate/{{ activation_key }}">http://{{site.domain}}/accounts/activate/{{ activation_key }}</a></li>
</ul>
<p>Solltest du nichts beantragt haben, ignoriere diese E-Mail einfach.
Du wirst keine weiteren Mails mehr von uns bekommen.</p>
<p><strong>Wichtig:</strong> Der Account muss innerhalb von <em>{{expiration_days}}</em> Tagen aktiviert werden,
ansonsten verfällt er automatisch.</p>
<p>mit freundlichen Grüßen</p>
<p>Das AniManga Team.</p>
{% endblock %}

View File

@@ -0,0 +1,13 @@
{% load i18n %}
Dear {{user}},
We received an account request on {{site.domain}} for your email address.
To activate your account please visit the following link:
http://{{site.domain}}/membership/activate/{{ activation_key }}/
If you do not want to open an account on {{site.domain}}, please ignore this email.
Your information will then be deleted in a few days time.
Best Regards,
The {{site.domain}} team.

View File

@@ -0,0 +1,15 @@
{% load i18n %}{% autoescape off %}
{% trans "You're receiving this e-mail because you requested a password reset" %}
{% blocktrans %}for your user account at {{ site_name }}{% endblocktrans %}.
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'django'.contrib.auth.views.password_reset_confirm uidb36=uid, token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}

View File

@@ -0,0 +1,3 @@
{% load i18n %}{% autoescape off %}
{% blocktrans %}Password reset on {{ site_name }}{% endblocktrans %}
{% endautoescape %}

View File

@@ -0,0 +1,32 @@
{% load i18n %}
<table>
<thead><tr>
<th>{% trans 'Start' %}<//th>
<th>{% trans 'Event' %}</th>
<th colspan="4">{% trans 'Players' %}</th>
<th>{% trans 'Kyu Points' %}</th>
<th>{% trans 'Dan Points' %}</th>
<th>{% trans 'Bonus Points' %}</th>
<th>{% trans 'Comment' %}</th>
</tr>
</thead>
{% for result in hanchan_list %}
<tr>
<td>{{ result.hanchan.start }}</td>
<td><a href="{{ result.hanchan.event.get_absolute_url }}">{{ result.hanchan.event.name }}</a></td>
{% if result.hanchan.valid %}
{% for player in result.hanchan.player_set.all %}
<td class="center"><a href="{% url 'membership-details' player.user.username %}">{{player.user}}</a><br/> {{player.score }}</td>
{% endfor %}
<td class="center">{{result.kyu_points}}</td>
<td class="center">{{result.dan_points}}</td>
{% else %}
<td colspan="6" class="center">{% trans 'This Hanchan does not validate' %}</td>
{% endif %}
<td class="center">{{result.bonus_points}}</td>
<td>{{ result.hanchan.comment }}</td>
</tr>
{% endfor %}
</table>

View File

@@ -0,0 +1,78 @@
{% extends "base.html" %}
{% load i18n comments %}
{% block title %}{{ membership.first_name }} {{membership.last_name}}{% endblock %}
{% block maincontent %}
<h2 class="grid_12">{% trans 'profile for' %} {{membership.user.username|title}}</h2>
{% if membership.profile %}
<img class="grid_3" src="{{membership.profile.url}}" alt="{% trans 'Profile Image' %}" />
{% else %}
<div class="grid_3"> Noch kein Foto hoch geladen</div>
{% endif %}
<div class="grid_6">
<ul>
<li><strong>Name:</strong> {{membership.first_name}} {{membership.last_name}}</li>
<li><strong>{% trans "Member Since" %}:</strong> {{membership.user.date_joined}}</li>
<li><strong>{% trans "Last Login" %}:</strong> {{membership.user.last_login}}</li>
{% if website %}<li><strong>Homepage:</strong> <a href="{{website}}">{{website}}</a></li>{% endif %}
</ul>
{% if kyu_dan_ranking %}
<h3>Mahjong</h3>
<ul>
{% if kyu_dan_ranking.dan %}
<li><strong>{{kyu_dan_ranking.dan}}. Dan: </strong> {{ kyu_dan_ranking.dan_points }} {% trans 'Points' %}</li>
{% elif kyu_dan_ranking.kyu%}
<li><strong>{{kyu_dan_ranking.kyu}}. Kyu: </strong> {{ kyu_dan_ranking.kyu_points }} {% trans 'Points' %}</li>
{% endif %}
<li><strong>{% trans 'Games Total' %}: </strong> {{ kyu_dan_ranking.hanchan_count }} Hanchans - {{kyu_dan_ranking.won_hanchans }} {% trans 'Won' %} / {{ kyu_dan_ranking.good_hanchans }} {% trans 'Good' %}</li>
<li><strong>{% trans 'Current Season' %}: </strong> {{ ladder_ranking.hanchan_count }} Hanchans - {{ ladder_ranking.won_hanchans }} {% trans 'Won' %} / {{ ladder_ranking.good_hanchans }} {% trans 'Good' %} </li>
</ul>
{% endif %}
</div>
{% ifequal membership.user user %}
<div class="grid_3">
<a href="{% url 'membership-edit' membership.user.username %}" class="button">
<img src="{{STATIC_URL}}icons/user_edit.png" alt="{% trans 'Edit Userprofile' %}" width="16" height="16"/>
{% trans "Edit Profile" %}
</a>
<a href="{% url 'password_change' %}" class="button">
<img src="{{STATIC_URL}}icons/lock_edit.png" alt="{% trans 'Change Password' %}" width="16" height="16"/>
{% trans 'Change Password' %}
</a>
<a class="button" href="{% url 'social:begin' 'facebook' %}" rel="nofollow">
<img src="{{STATIC_URL}}img/facebook.png" alt="{% trans 'Associate' %}" width="26" height="26"/>
{% blocktrans with 'Facebook' as name %}Associate with {{ name }}{% endblocktrans %}
</a>
<a class="button" href="{% url 'social:begin' 'twitter' %}" rel="nofollow">
<img src="{{STATIC_URL}}img/twitter.png" alt="{% trans 'Associate' %}" width="26" height="26"/>
{% blocktrans with 'Twitter' as name %}Associate with {{ name }}{% endblocktrans %}
</a>
<a class="button" href="{% url 'social:begin' 'google-oauth2' %}" rel="nofollow">
<img src="{{STATIC_URL}}img/google.png" alt="{% trans 'Associate' %}" width="26" height="26"/>
{% blocktrans with 'Google' as name %}Associate with {{ name }}{% endblocktrans %}
</a>
</div>
{% endifequal %}
{% block score_list %}
{% if kyu_dan_ranking %}
<ul class="tabs grid_12">
<li><a href="{% url 'player-ladder-score' membership.user.username %}">{% trans "Ladder Hanchans" %}</a></li>
<li><a href="{% url 'player-kyu-score' membership.user.username %}">{% trans "Kyu Hanchans" %}</a></li>
<li><a href="{% url 'player-dan-score' membership.user.username %}">{% trans "Dan Hanchans" %}</a></li>
<li><a href="{% url 'player-ladder-score' membership.user.username %}">{% trans "Invalid Hanchans" %}</a></li>
</ul>
{% endif %}
{% endblock %}
{% if membership %}
{% render_comment_list for membership %}
{% render_comment_form for membership %}
{% endif %}
{% endblock %}
{% block buttonbar%}{%endblock%}

View File

@@ -0,0 +1,41 @@
{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Edit Userprofile" %}{% endblock %}
{% block extra_head %}
<link rel="stylesheet" href="{{STATIC_URL}}css/jquery-ui-1.8.16.custom.css" type="text/css">
<script type="text/javascript" src="{{STATIC_URL}}js/jquery-ui-1.8.16.custom.min.js"></script>
{% endblock %}
{% block maincontent %}
<form method="post" action="" enctype="multipart/form-data" class="grid_12 clearfix">
<fieldset>
<legend>{% trans "Edit Userprofile" %}</legend>
{% csrf_token %}
{% include 'form.html' %}
<p class="buttonbar">
<button type="reset">
<img src="{{STATIC_URL}}icons/arrow_undo.png" alt="{% trans 'reset' %}" />
{% trans "Reset" %}
</button>
<button type="submit">
<img src="{{STATIC_URL}}icons/disk.png" alt="{% trans 'save' %}" />
{% trans "Save" %}
</button>
</p>
</fieldset>
</form>
{% endblock %}
{% block javascript %}
$(function() {
$( "#id_birthday" ).datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'yy-mm-dd',
yearRange: '-50,0',
firstDay: 1
});
});
{% endblock %}
{% block buttonbar %}{% endblock %}

View File

@@ -0,0 +1,31 @@
{% extends "base.html" %}
{% load i18n %}
{% load url from future %}
{% block title %}{% trans "Registration"%}{% endblock %}
{% block maincontent %}
<div class="grid_5">
<h2>{% trans "Registration" %}</h2>
<p>{% blocktrans %}
After you've provided your account data, you'll receive an email asking you to verify your email address.
You have to click on the link in this verification email to confirm your email address, otherwise your can't login.
{% endblocktrans %}</p>
</div>
<form method="post" action="{% url 'membership-register' %}" class="grid_7">
{% csrf_token %}
<fieldset>
<legend>{% trans "Registration"%}</legend>
{% include "form.html" %}
<p class="buttonbar">
<button type="reset"><img src="{{STATIC_URL}}icons/arrow_undo.png" alt="{% trans 'reset' %}" /> {% trans 'reset' %}</button>
<button type="submit"><img src="{{STATIC_URL}}icons/user_add.png" alt="{% trans 'register' %}" /> {% trans 'register' %}</button>
</p>
</fieldset>
</form>
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends "base.html" %}
{% load i18n %}
{% load url from future %}
{% block title %}{% trans "Activation sent"%}{% endblock %}
{% block content %}
<h2>{% trans "Activation sent"%}</h2>
<p>Bitte fülle das Anmeldeformular vollständig aus.
Es ist dabei wichtig eine gültige E-Mail Adresse anzugeben, welche du öfters abrufst.</p>
<p>Während der Registrierung schicken wir dir eine E-Mail, diese enthält einen Link zur Aktivierung.
Ohne diesen Schritt ist es nicht Möglich sich mit dem Account anzumelden.</p>
{% endblock %}

46
membership/urls.py Normal file
View File

@@ -0,0 +1,46 @@
'''
Created on 03.10.2011
@author: christian
'''
from django.conf.urls import * # @UnusedWildImport
from . import views
urlpatterns = patterns('',
url('', include('social.apps.django_app.urls', namespace='social')),
url('', include('django.contrib.auth.urls')),
url(r'^register/$',
views.RegisterForm.as_view(),
name="membership-register"),
url(r'^activate/(?P<activation_key>[\d\w]+)/$',
views.ActivateRegistration.as_view(),
name='membership-activate-registration'),
url(r'^activation_sent/$',
views.ActivationSent.as_view(),
name="membership-registration-complete"),
url(r'^(?P<username>[\-\.\d\w]+)/$',
views.MembershipDetail.as_view(),
name='membership-details'),
url(r'^(?P<username>[\-\.\d\w]+)/edit/$',
views.EditMembership.as_view(),
name="membership-edit")
)
"""
urlpatterns += patterns('social_auth.views',
url(r'^login/(?P<backend>[^/]+)/$', 'auth',
name='socialauth_begin'),
url(r'^complete/(?P<backend>[^/]+)/$', 'complete',
name='socialauth_complete'),
url(r'^associate/(?P<backend>[^/]+)/$', 'auth',
name='socialauth_associate_begin'),
url(r'^associate/complete/(?P<backend>[^/]+)/$', 'complete',
name='socialauth_associate_complete'),
url(r'^disconnect/(?P<backend>[^/]+)/$', 'disconnect',
name='socialauth_disconnect'),
url(r'^disconnect/(?P<backend>[^/]+)/(?P<association_id>[^/]+)/$',
'disconnect',
name='socialauth_disconnect_individual'),
)
"""

109
membership/views.py Normal file
View File

@@ -0,0 +1,109 @@
from django import http
from django.conf import settings
from django.contrib import auth, messages
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from django.views import generic
from mahjong_ranking.models import KyuDanRanking, LadderRanking, LadderSeason
import forms
import models
from utils import mixins
class ActivateRegistration(generic.DetailView):
'''
Activates the Registration of an User and logs him in
'''
template_name = 'membership/activation_error.html'
def get(self, request, **kwargs):
activation_key = self.kwargs.get('activation_key')
user = self.get_user(activation_key)
print 'User: ', user
if user:
return self.login(user)
else:
self.object = user
context = self.get_context_data()
return self.render_to_response(context)
def get_context_data(self, **kwargs):
context = generic.DetailView.get_context_data(self, **kwargs)
context.update({
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
'activation_key': self.kwargs.get('activation_key'),
})
return context
def get_user(self, activation_key):
user = models.ActivationRequest.objects.activate(activation_key)
if user:
return user
elif self.request.user.is_authenticated():
return self.request.user
else:
return None
def login(self, user):
backend = auth.get_backends()[0]
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) # @IgnorePep8
auth.login(self.request, user)
messages.success(self.request, _('Activation successful. \
You can now login anytime with you username and password.'))
redirect_url = reverse('membership-edit', args=(user.username,))
return http.HttpResponseRedirect(redirect_url) # @IgnorePep8
class ActivationSent(generic.TemplateView):
template_name = 'membership/activation_sent.html'
class EditMembership(mixins.LoginRequiredMixin, generic.UpdateView):
form_class = forms.MembershipForm
def get_object(self, queryset=None):
if self.request.user.has_perm('membership.change_membership'):
return models.Membership.objects.get(
username=self.kwargs['username'])
else:
return models.Membership.objects.get(user=self.request.user)
def form_valid(self, form):
messages.success(self.request, _('User Profile changed successfully'))
return generic.UpdateView.form_valid(self, form)
class MembershipDetail(mixins.LoginRequiredMixin, generic.DetailView):
model = models.Membership
def get_object(self, queryset=None):
if self.kwargs.get('username'):
return models.Membership.objects.get(username=self.kwargs['username'])
elif self.request.user.is_authenticated():
return models.Membership.objects.get(user=self.request.user)
def get_context_data(self, **kwargs):
context = generic.DetailView.get_context_data(self, **kwargs)
try:
context['kyu_dan_ranking'] = KyuDanRanking.objects.get(
user_id=self.object.user_id)
except:
context['kyu_dan_ranking'] = None
try:
context['ladder_ranking'] = LadderRanking.objects.get(
user_id=self.object.user_id,
season=LadderSeason.objects.current())
except:
context['ladder_ranking'] = LadderRanking(user=self.object.user)
return context
class RegisterForm(generic.FormView):
form_class = forms.RegistrationForm
success_url = '/membership/activation_sent/'
template_name = 'membership/register_form.html'
def form_valid(self, form):
form.save()
return generic.FormView.form_valid(self, form)