Anpassungen für das Hosting bei Djangoeurope und damit verbundenen Versionen Django 1.8 und Python 2.7
This commit is contained in:
committed by
Christian Berg
parent
cb4b15b3c6
commit
b96b485b61
1
src/membership/__init__.py
Normal file
1
src/membership/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
PAID_MEMBERSHIP_GROUP = 2
|
||||
72
src/membership/admin.py
Normal file
72
src/membership/admin.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
Created on 19.09.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
# import stuff we need from django
|
||||
from django.contrib import admin
|
||||
from django.utils.translation import ugettext as _
|
||||
from imagekit.admin import AdminThumbnail
|
||||
|
||||
from membership.models import Membership, ActivationRequest
|
||||
|
||||
|
||||
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)
|
||||
150
src/membership/forms.py
Normal file
150
src/membership/forms.py
Normal file
@@ -0,0 +1,150 @@
|
||||
"""
|
||||
Created on 03.10.2011
|
||||
|
||||
@author: Christian
|
||||
"""
|
||||
from django.conf import settings
|
||||
from django.contrib import auth
|
||||
from django.contrib.sites.models import Site
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from . import models
|
||||
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 = auth.get_user_model()
|
||||
fields = ('first_name', 'last_name', 'username', 'email',)
|
||||
|
||||
def clean_username(self):
|
||||
"""
|
||||
Validate that the username is not already in use.
|
||||
"""
|
||||
try:
|
||||
auth.get_user_model().objects.get(
|
||||
username__iexact=self.cleaned_data['username']
|
||||
)
|
||||
except auth.get_user_model().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 auth.get_user_model().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) # @IgnorePep8
|
||||
self.send_email(activation)
|
||||
return user
|
||||
396
src/membership/locale/de/LC_MESSAGES/django.po
Normal file
396
src/membership/locale/de/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,396 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: kasu.membership\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-01-05 19:23+0100\n"
|
||||
"PO-Revision-Date: 2014-12-08 16:18+0100\n"
|
||||
"Last-Translator: Christian Berg <xeniac.at@gmail.com>\n"
|
||||
"Language-Team: Kasu <verein@kasu.at>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Translated-Using: django-rosetta 0.7.2\n"
|
||||
"X-Generator: Poedit 1.6.11\n"
|
||||
|
||||
#: admin.py:21
|
||||
msgid "Activate selected User"
|
||||
msgstr "Ausgewählte Benutzer freischalten"
|
||||
|
||||
#: admin.py:30
|
||||
msgid "Cleanup selected Activation Requests"
|
||||
msgstr "Ausgewählte Aktivierungsanfragen bereinigen"
|
||||
|
||||
#: admin.py:52 models.py:193 models.py:252
|
||||
msgid "Membership"
|
||||
msgstr "Mitgliedschaft"
|
||||
|
||||
#: forms.py:19
|
||||
msgid "birthday"
|
||||
msgstr "Geburtstag"
|
||||
|
||||
#: forms.py:32 forms.py:39 forms.py:46 forms.py:53
|
||||
msgid ""
|
||||
"For your membership, we need this. Please fill out this field "
|
||||
"yet."
|
||||
msgstr "Diese Angabe wird für eine Mitgliedschaft benötigt, bitte ausfüllen."
|
||||
|
||||
#: forms.py:59
|
||||
msgid ""
|
||||
"For your membership, we need this. Please fill out this field "
|
||||
"yet."
|
||||
msgstr "Diese Angabe wird für eine Mitgliedschaft benötigt, bitte ausfüllen."
|
||||
|
||||
#: forms.py:75 models.py:182
|
||||
msgid "Given Name"
|
||||
msgstr "Vorname"
|
||||
|
||||
#: forms.py:77 models.py:183
|
||||
msgid "Last Name"
|
||||
msgstr "Nachname"
|
||||
|
||||
#: forms.py:79
|
||||
msgid "Username"
|
||||
msgstr "Benutzername"
|
||||
|
||||
#: forms.py:80
|
||||
msgid ""
|
||||
"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."
|
||||
msgstr ""
|
||||
"Der Benutzername kann aus den Buchstaben A-Z, Ziffern und dem Unterstrich "
|
||||
"bestehen. Es sollte wenigstens 2, aber maximal 30 Zeichen lang sein. Das "
|
||||
"erste Zeichen muss ein Buchstabe sein."
|
||||
|
||||
#: forms.py:85
|
||||
msgid "password"
|
||||
msgstr "Passwort"
|
||||
|
||||
#: forms.py:87
|
||||
msgid "password (again)"
|
||||
msgstr "Passwort (wiederholen)"
|
||||
|
||||
#: forms.py:104
|
||||
msgid "This username is already taken. Please choose another."
|
||||
msgstr "Diesen Benutzername ist schon vergeben. Bitte einen anderen auswählen."
|
||||
|
||||
#: forms.py:113
|
||||
msgid ""
|
||||
"This email address is already in use. Please supply a different "
|
||||
"email address."
|
||||
msgstr "Die E-Mail Adresse wird schon verwendet. Bitte eine andere angeben."
|
||||
|
||||
#: forms.py:122
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr "Die beiden Passwörter passen nicht."
|
||||
|
||||
#: models.py:22
|
||||
msgid "Male"
|
||||
msgstr "Männlich"
|
||||
|
||||
#: models.py:23
|
||||
msgid "Female"
|
||||
msgstr "Weiblich"
|
||||
|
||||
#: models.py:91
|
||||
msgid "user"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: models.py:93
|
||||
msgid "activation key"
|
||||
msgstr "Aktivierungsschlüssel"
|
||||
|
||||
#: models.py:97
|
||||
msgid "pending activation"
|
||||
msgstr "Ausstehende Aktivierung"
|
||||
|
||||
#: models.py:98
|
||||
msgid "pending activations"
|
||||
msgstr "Wartende Aktivierungen"
|
||||
|
||||
#: models.py:101
|
||||
#, python-format
|
||||
msgid "user registration for %s"
|
||||
msgstr "Benutzerregistrierung für %s"
|
||||
|
||||
#: models.py:176
|
||||
msgid "Nickname"
|
||||
msgstr "Spitzname"
|
||||
|
||||
#: models.py:178
|
||||
msgid "Gender"
|
||||
msgstr "Geschlecht"
|
||||
|
||||
#: models.py:184
|
||||
msgid "Email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: models.py:195
|
||||
msgid ""
|
||||
"Yes, I confirm that I am in agreement with the statutes and would "
|
||||
"like to become a member."
|
||||
msgstr "Ja, ich bin mit den Statuen einverstanden und möchte Mitglied werden."
|
||||
|
||||
#: models.py:198
|
||||
msgid "Birthday Date"
|
||||
msgstr "Geburtstag"
|
||||
|
||||
#: models.py:200
|
||||
msgid "Telephone"
|
||||
msgstr "Telefon"
|
||||
|
||||
#: models.py:206
|
||||
msgid "Address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: models.py:212
|
||||
msgid "Postcode"
|
||||
msgstr "Postleitzahl"
|
||||
|
||||
#: models.py:217
|
||||
msgid "Town/City"
|
||||
msgstr "Ort"
|
||||
|
||||
#: models.py:225
|
||||
msgid "Paid until"
|
||||
msgstr "Bezahlt bis"
|
||||
|
||||
#: models.py:231
|
||||
msgid "Confirmed"
|
||||
msgstr "Bestätigt"
|
||||
|
||||
#: models.py:233
|
||||
msgid "This person has paid the membership fee."
|
||||
msgstr "Diese Person hat ihre Mitgliedschaft bezahlt"
|
||||
|
||||
#: models.py:253
|
||||
msgid "Memberships"
|
||||
msgstr "Mitgliedschaften"
|
||||
|
||||
#: models.py:256
|
||||
#, python-format
|
||||
msgid "Userprofile for %s"
|
||||
msgstr "Benutzerprofil für %s"
|
||||
|
||||
#: views.py:54
|
||||
msgid ""
|
||||
"Activation successful. You can now login anytime with you username "
|
||||
"and password."
|
||||
msgstr ""
|
||||
"Die Aktivierung war erfolgreich. Du kannst dich ab jetzt jederzeit mit "
|
||||
"deinem Benutzernamen und Passwort anmelden."
|
||||
|
||||
#: views.py:75
|
||||
msgid "User Profile changed successfully"
|
||||
msgstr "Benutzerprofil erfolgreich geändert."
|
||||
|
||||
#: templates/membership/hanchan_table.html:5
|
||||
msgid "Start"
|
||||
msgstr "Beginn"
|
||||
|
||||
#: templates/membership/hanchan_table.html:6
|
||||
msgid "Event"
|
||||
msgstr "Termin"
|
||||
|
||||
#: templates/membership/hanchan_table.html:7
|
||||
msgid "Players"
|
||||
msgstr "Spieler"
|
||||
|
||||
#: templates/membership/hanchan_table.html:8
|
||||
msgid "Kyu Points"
|
||||
msgstr "Kyū Punkte"
|
||||
|
||||
#: templates/membership/hanchan_table.html:9
|
||||
msgid "Dan Points"
|
||||
msgstr "Dan Punkte"
|
||||
|
||||
#: templates/membership/hanchan_table.html:10
|
||||
msgid "Bonus Points"
|
||||
msgstr "Bonus Punkte"
|
||||
|
||||
#: templates/membership/hanchan_table.html:11
|
||||
msgid "Comment"
|
||||
msgstr "Anmerkung"
|
||||
|
||||
#: templates/membership/hanchan_table.html:26
|
||||
msgid "This Hanchan does not validate"
|
||||
msgstr "Diese Hanchan ist ungültig"
|
||||
|
||||
#: templates/membership/membership_detail.html:6
|
||||
msgid "profile for"
|
||||
msgstr "Profil für"
|
||||
|
||||
#: templates/membership/membership_detail.html:10
|
||||
msgid "Ladder Hanchans"
|
||||
msgstr "Ladder Hanchans"
|
||||
|
||||
#: templates/membership/membership_detail.html:11
|
||||
msgid "Kyu Hanchans"
|
||||
msgstr "Kyū Hanchans"
|
||||
|
||||
#: templates/membership/membership_detail.html:12
|
||||
msgid "Dan Hanchans"
|
||||
msgstr "Dan Hanchans"
|
||||
|
||||
#: templates/membership/membership_detail.html:13
|
||||
msgid "Invalid Hanchans"
|
||||
msgstr "Ungültige Hanchans"
|
||||
|
||||
#: templates/membership/membership_detail.html:14
|
||||
msgid "Mai-Star Games"
|
||||
msgstr "Mai-Star Spiele"
|
||||
|
||||
#: templates/membership/membership_detail.html:20
|
||||
msgid "Profile Image"
|
||||
msgstr "Profilbild"
|
||||
|
||||
#: templates/membership/membership_detail.html:28
|
||||
msgid "Member Since"
|
||||
msgstr "Mitglied seit"
|
||||
|
||||
#: templates/membership/membership_detail.html:29
|
||||
msgid "Last Login"
|
||||
msgstr "Letzte Anmeldung"
|
||||
|
||||
#: templates/membership/membership_detail.html:38
|
||||
#: templates/membership/membership_detail.html:40
|
||||
msgid "Points"
|
||||
msgstr "Punkte"
|
||||
|
||||
#: templates/membership/membership_detail.html:42
|
||||
msgid "Games Total"
|
||||
msgstr "Spiele gesamt"
|
||||
|
||||
#: templates/membership/membership_detail.html:43
|
||||
#: templates/membership/membership_detail.html:45
|
||||
msgid "Won"
|
||||
msgstr "Gewonnen"
|
||||
|
||||
#: templates/membership/membership_detail.html:43
|
||||
#: templates/membership/membership_detail.html:45
|
||||
msgid "Good"
|
||||
msgstr "Gut"
|
||||
|
||||
#: templates/membership/membership_detail.html:45
|
||||
msgid "Current Season"
|
||||
msgstr "Aktuelle Saison"
|
||||
|
||||
#: templates/membership/membership_detail.html:54
|
||||
#: templates/membership/membership_form.html:3
|
||||
#: templates/membership/membership_form.html:12
|
||||
msgid "Edit Userprofile"
|
||||
msgstr "Profil bearbeiten"
|
||||
|
||||
#: templates/membership/membership_detail.html:55
|
||||
msgid "Edit Profile"
|
||||
msgstr "Profil bearbeiten"
|
||||
|
||||
#: templates/membership/membership_detail.html:58
|
||||
#: templates/membership/membership_detail.html:59
|
||||
msgid "Change Password"
|
||||
msgstr "Passwort ändern"
|
||||
|
||||
#: templates/membership/membership_detail.html:62
|
||||
#: templates/membership/membership_detail.html:66
|
||||
#: templates/membership/membership_detail.html:70
|
||||
msgid "Associate"
|
||||
msgstr "Verbinden"
|
||||
|
||||
#: templates/membership/membership_detail.html:63
|
||||
#: templates/membership/membership_detail.html:67
|
||||
#: templates/membership/membership_detail.html:71
|
||||
#, python-format
|
||||
msgid "Associate with %(name)s"
|
||||
msgstr "Verbinde mit %(name)s"
|
||||
|
||||
#: templates/membership/membership_form.html:17
|
||||
#: templates/membership/register_form.html:33
|
||||
msgid "reset"
|
||||
msgstr "Zurücksetzen"
|
||||
|
||||
#: templates/membership/membership_form.html:18
|
||||
msgid "Reset"
|
||||
msgstr "Zurücksetzen"
|
||||
|
||||
#: templates/membership/membership_form.html:21
|
||||
msgid "save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: templates/membership/membership_form.html:22
|
||||
msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: templates/membership/register_form.html:5
|
||||
#: templates/membership/register_form.html:7
|
||||
msgid "Registration"
|
||||
msgstr "Registrieren"
|
||||
|
||||
#: templates/membership/register_form.html:16
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: templates/membership/register_form.html:21
|
||||
msgid "Security"
|
||||
msgstr "Sicherheit"
|
||||
|
||||
#: templates/membership/register_form.html:27
|
||||
msgid ""
|
||||
"After you've provided your account data, you'll\n"
|
||||
" receive an email asking you to verify your email address.\n"
|
||||
" You have to click on the link in this verification email to\n"
|
||||
" confirm your email address, otherwise your can't login.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"<p>Nach dem du deine Daten eingegeben hast, wirst du eine E-Mail zur "
|
||||
"Bestätigung bekommen.</p>\n"
|
||||
"<p>Bitte klicke auf den Link in dieser E-Mail zur Verifizierung, erst dann "
|
||||
"ist die Anmeldung möglich.</p>"
|
||||
|
||||
#: templates/membership/register_form.html:34
|
||||
msgid "register"
|
||||
msgstr "Registrieren"
|
||||
|
||||
#: templates/membership/register_successful.html:5
|
||||
#: templates/membership/register_successful.html:8
|
||||
msgid "Activation sent"
|
||||
msgstr "Aktivierung wurde zugesendet"
|
||||
|
||||
#: templates/membership/email/password_reset_email.html:2
|
||||
msgid "You're receiving this e-mail because you requested a password reset"
|
||||
msgstr ""
|
||||
"Du hast diese E-Mail erhalten, weil jemand die das Passwort zurücksetzen "
|
||||
"möchte. "
|
||||
|
||||
#: templates/membership/email/password_reset_email.html:3
|
||||
#, python-format
|
||||
msgid "for your user account at %(site_name)s"
|
||||
msgstr "Für deinen Benutzerzugang auf %(site_name)s"
|
||||
|
||||
#: templates/membership/email/password_reset_email.html:5
|
||||
msgid "Please go to the following page and choose a new password:"
|
||||
msgstr "Bitte gehe auf folgende Seite und wähle ein neues Passwort aus:"
|
||||
|
||||
#: templates/membership/email/password_reset_email.html:9
|
||||
msgid "Your username, in case you've forgotten:"
|
||||
msgstr "Dein Benutzername, für den Fall das du diesen vergessen hast:"
|
||||
|
||||
#: templates/membership/email/password_reset_email.html:11
|
||||
msgid "Thanks for using our site!"
|
||||
msgstr "Danke das du unsere Seite verwendest!"
|
||||
|
||||
#: templates/membership/email/password_reset_email.html:13
|
||||
#, python-format
|
||||
msgid "The %(site_name)s team"
|
||||
msgstr "Das %(site_name)s Team"
|
||||
|
||||
#: templates/membership/email/password_reset_subject.txt:2
|
||||
#, python-format
|
||||
msgid "Password reset on %(site_name)s"
|
||||
msgstr "Passwort auf %(site_name)s zurücksetzen"
|
||||
1
src/membership/management/__init__.py
Normal file
1
src/membership/management/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
#!/usr/bin/python
|
||||
1
src/membership/management/commands/__init__.py
Normal file
1
src/membership/management/commands/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
#!/usr/bin/python
|
||||
14
src/membership/management/commands/cleanup-registration.py
Normal file
14
src/membership/management/commands/cleanup-registration.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
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()
|
||||
|
||||
60
src/membership/management/commands/get-user.py
Normal file
60
src/membership/management/commands/get-user.py
Normal file
@@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
When you get an error email from your Django app telling you someone got a
|
||||
server error,
|
||||
it’s 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 optparse import make_option
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import auth
|
||||
from django.contrib.sessions.models import Session
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
|
||||
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 = auth.get_user_model().objects.get(pk=uid)
|
||||
except Session.DoesNotExist:
|
||||
self.stderr.write('Session "%s" does not exist' % session_key)
|
||||
continue
|
||||
except settings.AUTH_USER_MODEL.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)
|
||||
281
src/membership/models.py
Normal file
281
src/membership/models.py
Normal file
@@ -0,0 +1,281 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from datetime import timedelta
|
||||
from os import path
|
||||
import random
|
||||
import hashlib
|
||||
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
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 . import PAID_MEMBERSHIP_GROUP
|
||||
from utils import OverwriteStorage
|
||||
|
||||
|
||||
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.OneToOneField(
|
||||
settings.AUTH_USER_MODEL,
|
||||
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, user=None, username=None, **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 and not user:
|
||||
user = get_user_model().objects.get(username=username)
|
||||
return super(MembershipManager, self).get(user=user)
|
||||
except Membership.DoesNotExist:
|
||||
membership = Membership(
|
||||
user=user,
|
||||
nickname=user.username,
|
||||
first_name=user.first_name,
|
||||
last_name=user.last_name,
|
||||
email=user.email
|
||||
)
|
||||
membership.save()
|
||||
return membership
|
||||
|
||||
|
||||
class Membership(models.Model):
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL)
|
||||
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()
|
||||
24
src/membership/specs.py
Normal file
24
src/membership/specs.py
Normal file
@@ -0,0 +1,24 @@
|
||||
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,)
|
||||
18
src/membership/templates/membership/activation_error.html
Normal file
18
src/membership/templates/membership/activation_error.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}Account aktivierung fehlgeschlagen{% endblock %}
|
||||
|
||||
{% block teaser %}<h1>Account aktivierung fehlgeschlagen</h1>{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
<h2 class="grid_12">Aktivierung fehlgeschlagen</h2>
|
||||
<p class="grid_12">Leider war die Aktivierung des Schlüssels “{{ activation_key }}” 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 %}
|
||||
26
src/membership/templates/membership/activation_sent.html
Normal file
26
src/membership/templates/membership/activation_sent.html
Normal file
@@ -0,0 +1,26 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Bestätigungs E-Mail wurde abgeschickt{% endblock %}
|
||||
|
||||
{% block teaser %}<h1>Bestätigungs E-Mail wurde abgeschickt</h1>{% 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 %}
|
||||
@@ -0,0 +1,14 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Aktivierung erfolgreich{% endblock %}
|
||||
|
||||
{% block teaser %}<h1>Aktivierung erfolgreich</h1>{% 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 %}
|
||||
@@ -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 %}
|
||||
@@ -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.
|
||||
@@ -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 %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% load i18n %}{% autoescape off %}
|
||||
{% blocktrans %}Password reset on {{ site_name }}{% endblocktrans %}
|
||||
{% endautoescape %}
|
||||
32
src/membership/templates/membership/hanchan_table.html
Normal file
32
src/membership/templates/membership/hanchan_table.html
Normal 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>
|
||||
87
src/membership/templates/membership/membership_detail.html
Normal file
87
src/membership/templates/membership/membership_detail.html
Normal file
@@ -0,0 +1,87 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n comments %}
|
||||
|
||||
{% block title %}{{ membership.first_name }} {{membership.last_name}}{% endblock %}
|
||||
|
||||
{% block teaser %}<h1>{% trans 'profile for' %} {{membership.user.username|title}}</h1>{% endblock %}
|
||||
|
||||
{% block navigation %}
|
||||
<ul id="navigation">
|
||||
<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-invalid-score' membership.user.username %}">{% trans "Invalid Hanchans" %}</a></li>
|
||||
<li><a href="{% url 'maistar-player-games' membership.user.username %}">{% trans "Mai-Star Games" %}</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
{% 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 %} {% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block comments %}
|
||||
{% if membership %}
|
||||
{% render_comment_list for membership %}
|
||||
{% render_comment_form for membership %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttonbar%}{%endblock%}
|
||||
45
src/membership/templates/membership/membership_form.html
Normal file
45
src/membership/templates/membership/membership_form.html
Normal file
@@ -0,0 +1,45 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "Edit Userprofile" %}{% endblock %}
|
||||
|
||||
{% block teaser %}<h1>{% trans "Edit Userprofile" %}</h1>{% 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 %}
|
||||
39
src/membership/templates/membership/register_form.html
Normal file
39
src/membership/templates/membership/register_form.html
Normal file
@@ -0,0 +1,39 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n fieldset_extras %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block title %}{% trans "Registration"%}{% endblock %}
|
||||
|
||||
{% block teaser%}<h1>{% trans "Registration"%}</h1>{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
<form method="post" action="{% url 'membership-register' %}">
|
||||
{% csrf_token %}
|
||||
<fieldset class="grid_5">
|
||||
<legend>{% trans "Name"%}</legend>
|
||||
{% get_fieldset "first_name, last_name, username" from form as form1 %}
|
||||
{% with form1 as form %}{% include "form.html" %}{% endwith %}
|
||||
</fieldset>
|
||||
<fieldset class="grid_7">
|
||||
<legend>{% trans "Security"%}</legend>
|
||||
{% get_fieldset "email, password1, password2, recaptcha" from form as form2 %}
|
||||
{% with form2 as form %}{% include "form.html" %}{% endwith %}
|
||||
</fieldset>
|
||||
|
||||
<div class="grid_12">
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
16
src/membership/templates/membership/register_successful.html
Normal file
16
src/membership/templates/membership/register_successful.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block title %}{% trans "Activation sent"%}{% endblock %}
|
||||
|
||||
{% block teaser %}<h1>{% trans "Activation sent"%}</h1>{% 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 %}
|
||||
30
src/membership/urls.py
Normal file
30
src/membership/urls.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
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")
|
||||
)
|
||||
114
src/membership/views.py
Normal file
114
src/membership/views.py
Normal file
@@ -0,0 +1,114 @@
|
||||
from django import http
|
||||
from django.conf import settings
|
||||
from django.contrib import auth, messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import Http404
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views import generic
|
||||
|
||||
from mahjong_ranking.models import KyuDanRanking, LadderRanking, LadderSeason
|
||||
from utils import mixins
|
||||
from . import forms, models
|
||||
|
||||
|
||||
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)
|
||||
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):
|
||||
try:
|
||||
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)
|
||||
except models.Membership.DoesNotExist:
|
||||
raise Http404(_("No %(verbose_name)s found matching the query") %
|
||||
{'verbose_name': self.model._meta.verbose_name})
|
||||
|
||||
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 KyuDanRanking.DoesNotExist:
|
||||
context['kyu_dan_ranking'] = None
|
||||
try:
|
||||
context['ladder_ranking'] = LadderRanking.objects.get(
|
||||
user_id=self.object.user_id,
|
||||
season=LadderSeason.objects.current())
|
||||
except LadderRanking.DoesNotExist:
|
||||
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)
|
||||
Reference in New Issue
Block a user