Merge branch 'master' into member_lists

v1-0-stable
Schlabonski 9 years ago committed by GitHub
commit 2fdb326c4e

@ -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)

@ -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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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"

@ -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):

@ -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')

@ -1,3 +1,7 @@
{% load i18n %}
<head>
<title>{% trans "Unsubscribe" %}</title>
</head>
<p>{% trans "Sent confirmation mail to" %} <b>{{ email }}</b>. {% trans "Follow the link in your mail to confirm your unsubscription." %}</p>

@ -1,5 +1,11 @@
{% load i18n %}
<head>
<title>
{% trans "Unsubscribe" %}
</title>
</head>
<p><b>{% trans "Here you can unsubscribe from the newsletter" %}</b></p>
{% if error_message %}

@ -1,5 +1,9 @@
{% load i18n %}
<head>
<title>{% trans Unsubscribe %}</title>
</head>
<p>
{% trans "Successfully unsubscribed from the newsletter for " %}<b>{{ email }}</b>
</p>

@ -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)

@ -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)
admin.site.register(MaterialPart, MaterialAdmin)

@ -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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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"

@ -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,

@ -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)

@ -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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\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"

@ -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')

Loading…
Cancel
Save