diff --git a/jdav_web/mailer/admin.py b/jdav_web/mailer/admin.py index ffb476a..c12c4b1 100644 --- a/jdav_web/mailer/admin.py +++ b/jdav_web/mailer/admin.py @@ -1,16 +1,27 @@ -from django.contrib import admin +from django.contrib import admin, messages from django.contrib.admin import helpers from django.utils.translation import ugettext_lazy as _ from django.shortcuts import render +from django.db import models +from django import forms -from .models import Message +from .models import Message, Attachment + + +class AttachmentInline(admin.StackedInline): + model = Attachment + extra = 0 class MessageAdmin(admin.ModelAdmin): """Message creation view""" list_display = ('subject', 'from_addr', 'get_groups', 'sent') change_form_template = "mailer/change_form.html" + formfield_overrides = { + models.ManyToManyField: {'widget': forms.CheckboxSelectMultiple} + } + inlines = [AttachmentInline] actions = ['send_message'] def send_message(self, request, queryset): @@ -30,13 +41,19 @@ class MessageAdmin(admin.ModelAdmin): def response_change(self, request, obj): if "_send" in request.POST: - obj.submit() + if not obj.submit(): + messages.error(request, _("Failed to send message")) + else: + messages.info(request, _("Successfully sent message")) return super(MessageAdmin, self).response_change(request, obj) def response_add(self, request, obj): if "_send" in request.POST: - obj.submit() - return super(MessageAdmin, self).response_change(request, obj) + if not obj.submit(): + messages.error(request, _("Failed to send message")) + else: + messages.info(request, _("Successfully sent message")) + return super(MessageAdmin, self).response_add(request, obj) admin.site.register(Message, MessageAdmin) diff --git a/jdav_web/mailer/locale/de/LC_MESSAGES/django.po b/jdav_web/mailer/locale/de/LC_MESSAGES/django.po index fd5005e..abdddcc 100644 --- a/jdav_web/mailer/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/mailer/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-11-19 16:11+0100\n" +"POT-Creation-Date: 2017-01-14 15:55+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,51 +18,79 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: admin.py:20 +#: admin.py:32 msgid "Message sent" msgstr "Nachricht gesendet" -#: admin.py:28 +#: admin.py:40 msgid "Send message" msgstr "Nachricht verschicken" +#: admin.py:45 admin.py:53 +msgid "Failed to send message" +msgstr "Fehler beim senden der Email" + +#: admin.py:47 admin.py:55 +msgid "Successfully sent message" +msgstr "Email wurde erfolgreich verschickt" + #: apps.py:7 msgid "mailer" msgstr "Verteiler" -#: models.py:9 +#: models.py:34 msgid "from email" msgstr "Von Email" -#: models.py:10 +#: models.py:35 msgid "subject" msgstr "Betreff" -#: models.py:11 +#: models.py:36 msgid "content" msgstr "Inhalt" -#: models.py:12 +#: models.py:38 msgid "to group" msgstr "An Gruppe" -#: models.py:13 +#: models.py:39 msgid "sent" msgstr "Gesendet" -#: models.py:29 +#: models.py:46 +msgid "recipients" +msgstr "Empfänger" + +#: models.py:74 msgid "message" msgstr "Nachricht" -#: models.py:30 +#: models.py:75 msgid "messages" msgstr "Nachrichten" -#: models.py:32 +#: models.py:77 msgid "Can submit mails" msgstr "Kann Mails verschicken" -#: templates/admin/change_form.html:11 +#: models.py:86 +msgid "file" +msgstr "Datei" + +#: models.py:92 +msgid "Empty" +msgstr "Leer" + +#: models.py:95 +msgid "attachment" +msgstr "Anhang" + +#: models.py:96 +msgid "attachments" +msgstr "Anhänge" + +#: templates/mailer/change_form.html:11 msgid "Save and send mail" msgstr "Speichern und Email senden" @@ -89,6 +117,14 @@ msgstr "Senden" msgid "Cancel" msgstr "Abbruch" +#: templates/mailer/confirmation_sent.html:3 +msgid "Sent confirmation mail to" +msgstr "Bestätigungsmail gesendet an" + +#: templates/mailer/confirmation_sent.html:3 +msgid "Follow the link in your mail to confirm your unsubscription." +msgstr "" + #: templates/mailer/index.html:2 msgid "This is the mailer app!" msgstr "Das ist die Mailer App!" @@ -113,9 +149,71 @@ msgstr "Erhaltende Gruppe" msgid "Send mail" msgstr "Email senden" -#: views.py:33 +#: templates/mailer/subscribe.html:5 +msgid "Here you can register yourself to the newsletter" +msgstr "Hier kannst du dich für den Newsletter anmelden." + +#: templates/mailer/subscribe.html:16 +msgid "Prename" +msgstr "Vorname" + +#: templates/mailer/subscribe.html:21 +msgid "Lastname" +msgstr "Nachname" + +#: templates/mailer/subscribe.html:26 views.py:60 +msgid "Birthdate" +msgstr "Geburtsdatum" + +#: templates/mailer/subscribe.html:37 templates/mailer/unsubscribe.html:14 +msgid "Email address" +msgstr "Email-Adresse" + +#: templates/mailer/subscribe.html:42 +msgid "Register" +msgstr "Registrieren" + +#: templates/mailer/subscribed.html:3 +msgid "Subscribed successfully" +msgstr "Erfolgreich angemeldet" + +#: templates/mailer/unsubscribe.html:3 +msgid "Here you can unsubscribe from the newsletter" +msgstr "Hier kannst du dich vom Newsletter abmelden" + +#: templates/mailer/unsubscribe.html:19 +msgid "Unsubscribe" +msgstr "Vom Newsletter abmelden" + +#: templates/mailer/unsubscribed.html:4 +msgid "Successfully unsubscribed from the newsletter for " +msgstr "Newsletter erfolgreich abbestellt für " + +#: views.py:35 +msgid "Can't verify this link. Try again!" +msgstr "Ungültiger Link. Bitte nochmal versuchen!" + +#: views.py:47 +msgid "Please fill in every field" +msgstr "Bitte jedes Feld ausfüllen!" + +#: views.py:49 +msgid "Confirmation of unsubscription" +msgstr "Abmeldebestätigung" + +#: views.py:50 +msgid "" +"Click the link to unsubscribe to the newsletter of the JDAV\n" +"{}" +msgstr "Klicke auf den Link um dich von Newsletter des JDAV Ludwigsburg abzumelden" + +#: views.py:83 msgid "Please fill in every field!" msgstr "Bitte jedes Feld ausfüllen!" +#: views.py:90 +msgid "Member already exists" +msgstr "Mitglied schon vorhanden" + #~ msgid "History" #~ msgstr "Geschichte" diff --git a/jdav_web/mailer/mailutils.py b/jdav_web/mailer/mailutils.py index bd47c74..16c3ddb 100644 --- a/jdav_web/mailer/mailutils.py +++ b/jdav_web/mailer/mailutils.py @@ -1,16 +1,25 @@ -from django.core.mail import send_mass_mail, send_mail - - -def send(subject, content, sender, recipicient): - send_mail(subject, content, sender, [recipicient]) - - -def send_mass(subject, content, sender, recipicients): - data = [ - (subject, content, sender, [recipicient]) - for recipicient in recipicients] - print("sending data", data) - send_mass_mail(data) +from django.core.mail import EmailMessage + + +def send(subject, content, sender, recipients, reply_to=None, + attachments=None): + if type(recipients) != list: + recipients = [recipients] + if reply_to is not None: + kwargs = {"reply_to": [reply_to]} + else: + kwargs = {} + email = EmailMessage(subject, content, sender, recipients, **kwargs) + if attachments is not None: + for attach in attachments: + email.attach_file(attach) + try: + email.send() + except Exception as e: + print("Error when sending mail:", e) + return False + else: + return True def get_content(content): diff --git a/jdav_web/mailer/models.py b/jdav_web/mailer/models.py index 10770fc..d76ae5f 100644 --- a/jdav_web/mailer/models.py +++ b/jdav_web/mailer/models.py @@ -1,6 +1,31 @@ from django.db import models +from django.forms import forms from django.utils.translation import ugettext_lazy as _ -from .mailutils import send_mass, get_content +from .mailutils import send, get_content + +import os + + +class RestrictedFileField(models.FileField): + + def __init__(self, *args, **kwargs): + if "max_upload_size" in kwargs: + self.max_upload_size = kwargs.pop("max_upload_size") + + super(RestrictedFileField, self).__init__(*args, **kwargs) + + def clean(self, *args, **kwargs): + data = super(RestrictedFileField, self).clean(*args, **kwargs) + f = data.file + try: + if f._size > self.max_upload_size: + raise forms.ValidationError('Please keep filesize under {}. ' + 'Current filesize: ' + '{}'.format(self.max_upload_size, + f._size)) + except AttributeError as e: + print(e) + return data # Create your models here. @@ -29,10 +54,21 @@ class Message(models.Model): if not member.gets_newsletter: continue members.add(member) - send_mass(self.subject, get_content(self.content), - self.from_addr, [member.email for member in members]) - self.sent = True - self.save() + attach = [a.f.path for a in Attachment.objects.filter(msg__id=self.pk) + if a.f.name] + success = send(self.subject, get_content(self.content), + self.from_addr, [member.email for member in members], + attachments=attach) + for a in Attachment.objects.filter(msg__id=self.pk): + if a.f.name: + os.remove(a.f.path) + a.delete() + if success: + self.sent = True + self.save() + return True + else: + return False class Meta: verbose_name = _('message') @@ -40,3 +76,21 @@ class Message(models.Model): permissions = ( ("submit_mails", _("Can submit mails")), ) + + +class Attachment(models.Model): + """Represents an attachment to an email""" + msg = models.ForeignKey(Message, on_delete=models.CASCADE) + print("attachment class") + # file (not naming it file because of builtin) + f = RestrictedFileField(_('file'), + upload_to='attachments', + blank=True, + max_upload_size=10485760) + + def __str__(self): + return os.path.basename(self.f.name) if self.f.name else _("Empty") + + class Meta: + verbose_name = _('attachment') + verbose_name_plural = _('attachments') diff --git a/jdav_web/mailer/templates/mailer/confirmation_sent.html b/jdav_web/mailer/templates/mailer/confirmation_sent.html index 8f6b32d..8d40c4f 100644 --- a/jdav_web/mailer/templates/mailer/confirmation_sent.html +++ b/jdav_web/mailer/templates/mailer/confirmation_sent.html @@ -1,3 +1,7 @@ {% load i18n %} + + {% trans "Unsubscribe" %} + +

{% trans "Sent confirmation mail to" %} {{ email }}. {% trans "Follow the link in your mail to confirm your unsubscription." %}

diff --git a/jdav_web/mailer/templates/mailer/unsubscribe.html b/jdav_web/mailer/templates/mailer/unsubscribe.html index 5055820..53ba56e 100644 --- a/jdav_web/mailer/templates/mailer/unsubscribe.html +++ b/jdav_web/mailer/templates/mailer/unsubscribe.html @@ -1,5 +1,11 @@ {% load i18n %} + + + {% trans "Unsubscribe" %} + + +

{% trans "Here you can unsubscribe from the newsletter" %}

{% if error_message %} diff --git a/jdav_web/mailer/templates/mailer/unsubscribed.html b/jdav_web/mailer/templates/mailer/unsubscribed.html index 9c05d11..d7e4bd8 100644 --- a/jdav_web/mailer/templates/mailer/unsubscribed.html +++ b/jdav_web/mailer/templates/mailer/unsubscribed.html @@ -1,5 +1,9 @@ {% load i18n %} + + {% trans Unsubscribe %} + +

{% trans "Successfully unsubscribed from the newsletter for " %}{{ email }}

diff --git a/jdav_web/mailer/views.py b/jdav_web/mailer/views.py index 00f2e63..b8500d5 100644 --- a/jdav_web/mailer/views.py +++ b/jdav_web/mailer/views.py @@ -46,9 +46,10 @@ def unsubscribe(request): except (KeyError, Member.DoesNotExist): return render_unsubscribe(request, _("Please fill in every field")) else: - send_mail(_("Confirmation of unsubscription"), - _("Click the link to unsubscribe to the newsletter of" - " the JDAV\n{}".format(get_unsubscribe_link(member))), + send_mail("Abmeldebestätigung", + "Klicke auf den Link, um dich vom Newsletter des JDAV " + "Ludwigsburg " + "abzumelden\n{}".format(get_unsubscribe_link(member)), mail_root, email) return render_confirmation_sent(request, email) diff --git a/jdav_web/material/admin.py b/jdav_web/material/admin.py index f285118..0771630 100644 --- a/jdav_web/material/admin.py +++ b/jdav_web/material/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from django.utils. translation import ugettext_lazy as translate +from django.utils.translation import ugettext_lazy as _ from django.contrib.admin import SimpleListFilter from .models import MaterialPart, Ownership @@ -16,13 +16,13 @@ class OwnershipInline(admin.StackedInline): class NotTooOldFilter(SimpleListFilter): - title = translate('Age') + title = _('Age') parameter_name = 'age' def lookups(self, request, model_admin): return ( - ('too_old', translate('Not Too Old')), - ('not_too_old', translate('Too old')), + ('too_old', _('Not too old')), + ('not_too_old', _('Too old')), ) def queryset(self, request, queryset): @@ -31,7 +31,7 @@ class NotTooOldFilter(SimpleListFilter): if self.value() == 'not_too_old': return queryset.filter(pk__in=[x.pk for x in queryset.all() if not x.not_too_old()]) - + class MaterialAdmin(admin.ModelAdmin): """Edit view of a MaterialPart""" @@ -41,4 +41,4 @@ class MaterialAdmin(admin.ModelAdmin): list_filter = (NotTooOldFilter,) -admin.site.register(MaterialPart, MaterialAdmin) \ No newline at end of file +admin.site.register(MaterialPart, MaterialAdmin) diff --git a/jdav_web/material/locale/de/LC_MESSAGES/django.po b/jdav_web/material/locale/de/LC_MESSAGES/django.po index fd7587b..84940b1 100644 --- a/jdav_web/material/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/material/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-10-21 23:38+0200\n" +"POT-Creation-Date: 2017-01-14 16:49+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,6 +18,18 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +#: admin.py:19 +msgid "Age" +msgstr "Alter" + +#: admin.py:24 +msgid "Not too old" +msgstr "Nicht zu alt" + +#: admin.py:25 +msgid "Too old" +msgstr "Zu alt" + #: apps.py:7 msgid "material" msgstr "Material" @@ -27,10 +39,14 @@ msgid "name" msgstr "Name" #: models.py:18 +msgid "quantity" +msgstr "Anzahl" + +#: models.py:19 msgid "purchase date" msgstr "Kaufdatum" -#: models.py:19 +#: models.py:20 msgid "lifetime (years)" msgstr "Lebenszeit (Jahre)" @@ -38,30 +54,34 @@ msgstr "Lebenszeit (Jahre)" msgid "photo" msgstr "Bild" -#: models.py:35 +#: models.py:32 +msgid "Quantity" +msgstr "Anzahl" + +#: models.py:42 msgid "Not too old?" msgstr "Nicht zu alt?" -#: models.py:38 +#: models.py:45 msgid "material part" msgstr "Materialteil" -#: models.py:39 +#: models.py:46 msgid "material parts" msgstr "Materialteile" -#: models.py:45 +#: models.py:52 msgid "owner" msgstr "Besitzer" -#: models.py:46 +#: models.py:53 msgid "count" msgstr "Anzahl" -#: models.py:53 +#: models.py:60 msgid "ownership" msgstr "Besitztum" -#: models.py:54 +#: models.py:61 msgid "ownerships" msgstr "Besitztümer" diff --git a/jdav_web/material/models.py b/jdav_web/material/models.py index cc6226b..3e59978 100644 --- a/jdav_web/material/models.py +++ b/jdav_web/material/models.py @@ -25,13 +25,12 @@ class MaterialPart(models.Model): return self.name def quantity_real(self): - real = sum([o.count for o in Ownership.objects.filter(material__id = self.pk)]) + real = sum([o.count for o in Ownership.objects.filter(material__id=self.pk)]) return str(real) + '/' + str(self.quantity) quantity_real.admin_order_field = 'quantity' quantity_real.short_description = _('Quantity') - def not_too_old(self): """Returns wether the part should be replaced cause of age""" buy_time = timezone.make_aware(datetime.combine(self.buy_date, diff --git a/jdav_web/members/admin.py b/jdav_web/members/admin.py index 64f1a19..9a31cb8 100644 --- a/jdav_web/members/admin.py +++ b/jdav_web/members/admin.py @@ -11,7 +11,7 @@ from django import forms from django.contrib import admin from django.contrib.admin import DateFieldListFilter from django.utils.translation import ugettext_lazy as translate -from django.db.models import TextField +from django.db.models import TextField, ManyToManyField from django.forms import Textarea from .models import (Member, Group, MemberList, MemberOnList, Klettertreff, @@ -22,9 +22,11 @@ from .models import (Member, Group, MemberList, MemberOnList, Klettertreff, class MemberAdmin(admin.ModelAdmin): fields = ['prename', 'lastname', 'email', 'street', 'town', 'phone_number', 'phone_number_parents', 'birth_date', 'group', 'gets_newsletter', 'comments'] - list_display = ('name', 'street', 'town', 'phone_number', - 'phone_number_parents', 'birth_date', 'gets_newsletter', 'get_group', 'comments') + list_display = ('name', 'birth_date', 'gets_newsletter', 'get_group', 'comments') list_filter = ('group', 'gets_newsletter') + formfield_overrides = { + ManyToManyField: {'widget': forms.CheckboxSelectMultiple} + } class GroupAdmin(admin.ModelAdmin): @@ -149,6 +151,7 @@ class MemberListAdmin(admin.ModelAdmin): return response + class KlettertreffAdminForm(forms.ModelForm): class Meta: model = Klettertreff @@ -169,6 +172,10 @@ class KlettertreffAdmin(admin.ModelAdmin): inlines = [KlettertreffAttendeeInline] list_display = ['__str__', 'date', 'get_jugendleiter'] list_filter = [('date', DateFieldListFilter)] + formfield_overrides = { + ManyToManyField: {'widget': forms.CheckboxSelectMultiple} + } + admin.site.register(Member, MemberAdmin) admin.site.register(Group, GroupAdmin) diff --git a/jdav_web/members/locale/de/LC_MESSAGES/django.po b/jdav_web/members/locale/de/LC_MESSAGES/django.po index b845483..d684c27 100644 --- a/jdav_web/members/locale/de/LC_MESSAGES/django.po +++ b/jdav_web/members/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-10-21 23:37+0200\n" +"POT-Creation-Date: 2017-01-14 16:40+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,38 +18,118 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: apps.py:7 models.py:45 +#: apps.py:7 models.py:81 msgid "members" msgstr "Teilnehmer" -#: models.py:10 +#: models.py:13 msgid "name" msgstr "Name" -#: models.py:12 +#: models.py:15 msgid "minimum age (years)" msgstr "Mindestalter (Jahre)" -#: models.py:19 +#: models.py:22 models.py:39 msgid "group" msgstr "Gruppe" -#: models.py:20 +#: models.py:23 msgid "groups" msgstr "Gruppen" -#: models.py:28 +#: models.py:31 msgid "prename" msgstr "Vorname" -#: models.py:29 +#: models.py:32 msgid "last name" msgstr "Nachname" -#: models.py:31 +#: models.py:33 +msgid "street" +msgstr "Straße" + +#: models.py:34 +msgid "town" +msgstr "Stadt" + +#: models.py:35 +msgid "phone number" +msgstr "Telefonnummer" + +#: models.py:36 +msgid "parents phone number" +msgstr "Telefonnummer der Eltern" + +#: models.py:38 msgid "birth date" msgstr "Geburtsdatum" +#: models.py:40 +msgid "receives newsletter" +msgstr "Erhält den Newsletter" + #: models.py:44 +msgid "comments" +msgstr "Kommentare" + +#: models.py:77 +msgid "Group" +msgstr "Gruppe" + +#: models.py:80 msgid "member" msgstr "Teilnehmer" + +#: models.py:86 +msgid "Listname" +msgstr "Name der Liste" + +#: models.py:88 +msgid "date" +msgstr "Datum" + +#: models.py:89 +msgid "Comments" +msgstr "Kommentare" + +#: models.py:96 +msgid "Memberlist" +msgstr "Teilnehmerliste" + +#: models.py:97 +msgid "Memberlists" +msgstr "Teilnehmerlisten" + +#: models.py:104 models.py:109 models.py:139 models.py:143 +msgid "Member" +msgstr "Teilnehmer" + +#: models.py:106 +msgid "Comment" +msgstr "Kommentar" + +#: models.py:110 models.py:144 +msgid "Members" +msgstr "Teilnehmer" + +#: models.py:119 +msgid "Date" +msgstr "Datum" + +#: models.py:120 +msgid "Location" +msgstr "Ort" + +#: models.py:130 +msgid "Jugendleiter" +msgstr "Jugendleiter" + +#: models.py:133 +msgid "Klettertreff" +msgstr "Klettertreff" + +#: models.py:134 +msgid "Klettertreffs" +msgstr "Klettertreffs" diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py index 9815bae..6b7966c 100644 --- a/jdav_web/members/models.py +++ b/jdav_web/members/models.py @@ -38,7 +38,7 @@ class Member(models.Model): phone_number_parents = models.CharField(max_length=12, verbose_name=_('parents phone number'), default='', blank=True) email = models.EmailField(max_length=100, default="") birth_date = models.DateField(_('birth date')) # to determine the age - group = models.ManyToManyField(Group) + group = models.ManyToManyField(Group, verbose_name=_('group')) gets_newsletter = models.BooleanField(_('receives newsletter'), default=True) unsubscribe_key = models.CharField(max_length=32, default="") @@ -70,7 +70,7 @@ class Member(models.Model): def name(self): """Returning whole name (prename + lastname)""" return "{0} {1}".format(self.prename, self.lastname) - + def get_group(self): """Returns a string of groups in which the member is.""" groupstring = ''.join(g.name + ',\n' for g in self.group.all()) @@ -85,6 +85,7 @@ class Member(models.Model): class MemberList(models.Model): """Lets the user create a list of members in pdf format. """ + name = models.CharField(verbose_name='Activity', default='', max_length=50) place = models.CharField(verbose_name=_('Place'), default='', max_length=50) @@ -98,30 +99,39 @@ class MemberList(models.Model): ('Ausbildung', 'Ausbildung')) tour_type = MultiSelectField(choices=tour_type_choices, default='', max_choices=1) + def __str__(self): """String represenation""" return self.name + class Meta: + verbose_name = _('Memberlist') + verbose_name_plural = _('Memberlists') + class MemberOnList(models.Model): """ Connects members to a list of members. """ - member = models.ForeignKey(Member) + member = models.ForeignKey(Member, verbose_name=_('Member')) memberlist = models.ForeignKey(MemberList) comments = models.TextField(_('Comment'), default='', blank=True) + class Meta: + verbose_name = _('Member') + verbose_name_plural = _('Members') + class Klettertreff(models.Model): """ This model represents a Klettertreff event. - A Klettertreff can take a date, location, Jugendleiter, attending members as - input. + A Klettertreff can take a date, location, Jugendleiter, attending members + as input. """ date = models.DateField(_('Date'), default=datetime.today) location = models.CharField(_('Location'), default='', max_length=60) jugendleiter = models.ManyToManyField(Member) - + def __str__(self): return self.location + ' ' + self.date.strftime('%d.%m.%Y') @@ -131,8 +141,16 @@ class Klettertreff(models.Model): get_jugendleiter.short_description = _('Jugendleiter') + class Meta: + verbose_name = _('Klettertreff') + verbose_name_plural = _('Klettertreffs') + + class KlettertreffAttendee(models.Model): """Connects members to Klettertreffs.""" - member = models.ForeignKey(Member) + member = models.ForeignKey(Member, verbose_name=_('Member')) klettertreff = models.ForeignKey(Klettertreff) + class Meta: + verbose_name = _('Member') + verbose_name_plural = _('Members')