Merge branch 'master' into member_lists

v1-0-stable
Schlabonski 9 years ago
commit d5d8ae4099

2
.gitignore vendored

@ -93,6 +93,8 @@ jdav_web/db.sqlite3
# test images for file upload
*.jpeg
*.png
jdav_web/media
jdav_web/*/migrations
*.py.swp
# django database migrations

@ -4,3 +4,15 @@ This repository has the purpose to develop a webapplication that can be used by
JDAV to send newsletters, manage user lists and keep material lists up to date.
As this repository is also meant to be a base for exchange during development, feel free
to contribute ideas in form of edits to this README, issues, landmarks, projects, wiki entries, ...
# Useful stuff
## Reset database for certain app
The following can be useful in case that automatic migrations throw errors.
1. delete everything in the migrations folder except for __init__.py.
2. drop into my MySQL console and do: DELETE FROM django_migrations WHERE app='my_app'
3. while at the MySQL console, drop all of the tables associated with my_app.
4. re-run ./manage.py makemigrations my_app - this generates a 0001_initial.py file in my migrations folder.
5. run ./manage migrate my_app - I expect this command to re-build all my tables, but instead it says: "No migrations to apply."

@ -37,6 +37,7 @@ INSTALLED_APPS = [
'startpage.apps.StartpageConfig',
'material.apps.MaterialConfig',
'members.apps.MembersConfig',
'mailer.apps.MailerConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
@ -133,3 +134,12 @@ STATIC_URL = '/static/'
# Locale files (translations)
LOCALE_PATHS = (os.path.join(BASE_DIR, 'locale'),)
# Email setup
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False

@ -23,6 +23,7 @@ urlpatterns = static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += i18n_patterns(
url(r'^admin/', admin.site.urls),
url(r'^newsletter/', include('mailer.urls', namespace="mailer")),
url(r'^$', include('startpage.urls')),
)

@ -0,0 +1,42 @@
from django.contrib import admin
from django.contrib.admin import helpers
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import render
from .models import Message
class MessageAdmin(admin.ModelAdmin):
"""Message creation view"""
list_display = ('subject', 'from_addr', 'get_groups', 'sent')
change_form_template = "mailer/change_form.html"
actions = ['send_message']
def send_message(self, request, queryset):
print("calling send_message")
if request.POST.get('confirmed'):
for msg in queryset:
msg.submit()
self.message_user(request, _("Message sent"))
else:
context = {
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
'mails': queryset,
'ids': queryset.values_list("id"),
'some_sent': any(m.sent for m in queryset)}
return render(request, 'mailer/confirm_send.html', context)
send_message.short_description = _("Send message")
def response_change(self, request, obj):
if "_send" in request.POST:
obj.submit()
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)
admin.site.register(Message, MessageAdmin)

@ -0,0 +1,7 @@
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _
class MailerConfig(AppConfig):
name = 'mailer'
verbose_name = _('mailer')

@ -0,0 +1,121 @@
# 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.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-11-19 16:11+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"
"Language: \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"
#: admin.py:20
msgid "Message sent"
msgstr "Nachricht gesendet"
#: admin.py:28
msgid "Send message"
msgstr "Nachricht verschicken"
#: apps.py:7
msgid "mailer"
msgstr "Verteiler"
#: models.py:9
msgid "from email"
msgstr "Von Email"
#: models.py:10
msgid "subject"
msgstr "Betreff"
#: models.py:11
msgid "content"
msgstr "Inhalt"
#: models.py:12
msgid "to group"
msgstr "An Gruppe"
#: models.py:13
msgid "sent"
msgstr "Gesendet"
#: models.py:29
msgid "message"
msgstr "Nachricht"
#: models.py:30
msgid "messages"
msgstr "Nachrichten"
#: models.py:32
msgid "Can submit mails"
msgstr "Kann Mails verschicken"
#: templates/admin/change_form.html:11
msgid "Save and send mail"
msgstr "Speichern und Email senden"
#: templates/mailer/confirm_send.html:7
msgid "Do you really want to send these mails?"
msgstr "Möchtest du diese Emails wirklich verschicken?"
#: templates/mailer/confirm_send.html:13
msgid "already sent"
msgstr "schon verschickt"
#: templates/mailer/confirm_send.html:19
msgid ""
"Some messages have already been sent! Do you really want to resend them?"
msgstr ""
"Einige Emails wurden schon versendet! Möchtest du diese wirklich nochmal "
"senden?"
#: templates/mailer/confirm_send.html:30
msgid "Send"
msgstr "Senden"
#: templates/mailer/confirm_send.html:35
msgid "Cancel"
msgstr "Abbruch"
#: templates/mailer/index.html:2
msgid "This is the mailer app!"
msgstr "Das ist die Mailer App!"
#: templates/mailer/send.html:2
msgid "Here you can send new emails!"
msgstr "Hier kannst du neue Emails verschicken!"
#: templates/mailer/send.html:11
msgid "Subject:"
msgstr "Betreff"
#: templates/mailer/send.html:14
msgid "Content:"
msgstr "Inhalt:"
#: templates/mailer/send.html:17
msgid "Receiving group:"
msgstr "Erhaltende Gruppe"
#: templates/mailer/send.html:24
msgid "Send mail"
msgstr "Email senden"
#: views.py:33
msgid "Please fill in every field!"
msgstr "Bitte jedes Feld ausfüllen!"
#~ msgid "History"
#~ msgstr "Geschichte"

@ -0,0 +1,43 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.mail import send_mass_mail
# Create your models here.
class Message(models.Model):
"""Represents a message that can be sent to some members"""
from_addr = models.EmailField(_('from email'))
subject = models.CharField(_('subject'), max_length=50)
content = models.TextField(_('content'))
to_groups = models.ManyToManyField('members.Group',
verbose_name=_('to group'))
sent = models.BooleanField(_('sent'), default=False)
def __str__(self):
return self.subject
def get_groups(self):
return ", ".join([g.name for g in self.to_groups.all()])
get_groups.short_description = _('recipicients')
def submit(self):
"""Sends the mail to the specified group of members"""
members = set()
for group in self.to_groups.all():
group_members = group.member_set.all()
for member in group_members:
members.add(member)
data = [
(self.subject, self.content, self.from_addr, [member.email])
for member in members
]
send_mass_mail(data)
self.sent = True
self.save()
class Meta:
verbose_name = _('message')
verbose_name_plural = _('messages')
permissions = (
("submit_mails", _("Can submit mails")),
)

@ -0,0 +1,15 @@
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block content %}
{{ block.super }}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'mailer/change_style.css' %}" />
<script type="text/javascript">
(function($){
$('<input type="submit" value="{% trans 'Save and send mail' %}" name="_send" class="send_mail"/>')
.prependTo('div.submit-row');
})(django.jQuery);
</script>
{% endblock %}

@ -0,0 +1,38 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% load static %}
{% block content %}
<link rel="stylesheet" type="text/css" href="{% static 'admin/style.css' %}" />
<p>{% trans "Do you really want to send these mails?" %}</p>
<ul>
{% for mail in mails %}
<li>
{{mail.subject}}
{% if mail.sent %}
({% trans "already sent" %})
{%endif %}
</li>
{% endfor %}
</ul>
{% if some_sent %}
<p><b>{% trans "Some messages have already been sent! Do you really want to resend them?" %}</b></p>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<input type="hidden" name="confirmed" value="yes">
<input type="hidden" name="action" value="send_message">
{% for id in ids %}
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ id.0 }}">
{% endfor %}
<input type="submit" value={% trans "Send" %}>
</form>
<form action="" method="post" class="cancel">
{% csrf_token %}
<input type="submit" value={% trans "Cancel" %}>
</form>
{% endblock %}

@ -0,0 +1,3 @@
{% load i18n %}
{% trans "This is the mailer app!" %}
<p><a href={% url 'mailer:send' %}>New Mail</a></p>

@ -0,0 +1,25 @@
{% load i18n %}
{% trans "Here you can send new emails!" %}
{% if error_message %}
<p><b>{{ error_message }}</b></p>
{% endif %}
<form action="{% url 'mailer:send_mail' %}" method="post">
{% csrf_token %}
{% trans "Subject:" %}<br>
<input type="text" name="subject"><br>
{% trans "Content:" %}<br>
<textarea rows="10" cols="80" name="content"></textarea><br>
{% trans "Receiving group:" %}<br>
<select name="to_group">
{% for group in groups %}
<option value="{{ group.id }}">{{ group.name }}</option>
{% endfor %}
</select><br>
<input type="submit" value="{% trans "Send mail" %}">
</form>

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

@ -0,0 +1,10 @@
from django.conf.urls import url
from . import views
app_name = "mailer"
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^send_mail', views.send_mail, name='send_mail'),
url(r'^send', views.send, name='send')
]

@ -0,0 +1,40 @@
from django.shortcuts import render
from django.utils.translation import ugettext_lazy as _
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import permission_required
from members.models import Group
from .models import Message
@permission_required('mailer.submit_mails', login_url='/admin/')
def index(request):
"""This is the main newsletter view"""
return render(request, 'mailer/index.html')
@permission_required('mailer.submit_mails', login_url='/admin/')
def send(request):
return render(request, 'mailer/send.html', {
'groups': Group.objects.all()
})
@permission_required('mailer.submit_mails', login_url='/admin/')
def send_mail(request):
try:
subject = request.POST['subject']
content = request.POST['content']
to_group = Group.objects.get(pk=request.POST['to_group'])
except (KeyError, Group.DoesNotExist):
return render(request, 'mailer/send.html', {
'error_message': _("Please fill in every field!"),
'groups': Group.objects.all()
})
else:
msg = Message(subject=subject, content=content, to_group=to_group)
msg.submit()
msg.save()
return HttpResponseRedirect(reverse('mailer:index'))

@ -1,4 +1,6 @@
from django.contrib import admin
from django.utils. translation import ugettext_lazy as translate
from django.contrib.admin import SimpleListFilter
from .models import MaterialPart, Ownership
@ -13,10 +15,30 @@ class OwnershipInline(admin.StackedInline):
extra = 0
class NotTooOldFilter(SimpleListFilter):
title = translate('Age')
parameter_name = 'age'
def lookups(self, request, model_admin):
return (
('too_old', translate('Not Too Old')),
('not_too_old', translate('Too old')),
)
def queryset(self, request, queryset):
if self.value() == 'too_old':
return queryset.filter(pk__in=[x.pk for x in queryset.all() if x.not_too_old()])
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"""
list_display = ('name', 'buy_date', 'lifetime', 'not_too_old', 'photo')
inlines = [OwnershipInline]
list_filter = (NotTooOldFilter,)
admin.site.register(MaterialPart, MaterialAdmin)
admin.site.register(MaterialPart, MaterialAdmin)

@ -0,0 +1,38 @@
[
{
"model": "material.MaterialPart",
"pk": "1",
"fields": {
"name": "Seil 40m grün",
"buy_date": "2016-01-01",
"lifetime": "3"
}
},
{
"model": "material.MaterialPart",
"pk": "2",
"fields": {
"name": "Seil 40m blau",
"buy_date": "2012-01-01",
"lifetime": "3"
}
},
{
"model": "material.MaterialPart",
"pk": "3",
"fields": {
"name": "Seil 60m gelb",
"buy_date": "2013-01-01",
"lifetime": "3"
}
},
{
"model": "material.MaterialPart",
"pk": "4",
"fields": {
"name": "Seil 60m blau",
"buy_date": "2016-01-01",
"lifetime": "3"
}
}
]

@ -1,3 +1,3 @@
Django==1.10.2
Pillow==3.4.2
mysqlclient==1.3.9
PyMySQL==0.7.9

Loading…
Cancel
Save