Add notification settings and forms for email notifications
This commit is contained in:
parent
93f5f05a33
commit
bb8949af76
19 changed files with 435 additions and 23 deletions
|
@ -21,7 +21,14 @@ class FallenBirdAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
@admin.register(Bird)
|
@admin.register(Bird)
|
||||||
class BirdAdmin(admin.ModelAdmin):
|
class BirdAdmin(admin.ModelAdmin):
|
||||||
list_display = ["name"]
|
list_display = ["name", "melden_an_naturschutzbehoerde", "melden_an_jagdbehoerde", "melden_an_wildvogelhilfe_team"]
|
||||||
|
list_filter = ["melden_an_naturschutzbehoerde", "melden_an_jagdbehoerde", "melden_an_wildvogelhilfe_team"]
|
||||||
|
fields = ('name', 'description', 'melden_an_naturschutzbehoerde', 'melden_an_jagdbehoerde', 'melden_an_wildvogelhilfe_team')
|
||||||
|
|
||||||
|
def save_model(self, request, obj, form, change):
|
||||||
|
if not change: # Only set created_by when creating new object
|
||||||
|
obj.created_by = request.user
|
||||||
|
super().save_model(request, obj, form, change)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(BirdStatus)
|
@admin.register(BirdStatus)
|
||||||
|
|
|
@ -75,3 +75,30 @@ class BirdEditForm(forms.ModelForm):
|
||||||
"finder": _("Finder"),
|
"finder": _("Finder"),
|
||||||
"comment": _("Bermerkung"),
|
"comment": _("Bermerkung"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class BirdSpeciesForm(forms.ModelForm):
|
||||||
|
"""Form for editing Bird species with notification settings."""
|
||||||
|
class Meta:
|
||||||
|
model = Bird
|
||||||
|
fields = [
|
||||||
|
"name",
|
||||||
|
"description",
|
||||||
|
"species",
|
||||||
|
"melden_an_naturschutzbehoerde",
|
||||||
|
"melden_an_jagdbehoerde",
|
||||||
|
"melden_an_wildvogelhilfe_team",
|
||||||
|
]
|
||||||
|
labels = {
|
||||||
|
"name": _("Bezeichnung"),
|
||||||
|
"description": _("Erläuterungen"),
|
||||||
|
"species": _("Art"),
|
||||||
|
"melden_an_naturschutzbehoerde": _("Melden an Naturschutzbehörde"),
|
||||||
|
"melden_an_jagdbehoerde": _("Melden an Jagdbehörde"),
|
||||||
|
"melden_an_wildvogelhilfe_team": _("Melden an Wildvogelhilfe-Team"),
|
||||||
|
}
|
||||||
|
help_texts = {
|
||||||
|
"melden_an_naturschutzbehoerde": _("Automatische E-Mail-Benachrichtigung an Naturschutzbehörde senden"),
|
||||||
|
"melden_an_jagdbehoerde": _("Automatische E-Mail-Benachrichtigung an Jagdbehörde senden"),
|
||||||
|
"melden_an_wildvogelhilfe_team": _("Automatische E-Mail-Benachrichtigung an Wildvogelhilfe-Team senden"),
|
||||||
|
}
|
||||||
|
|
28
app/bird/migrations/0007_add_notification_settings.py
Normal file
28
app/bird/migrations/0007_add_notification_settings.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated manually for notification settings
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bird', '0006_alter_fallenbird_options_alter_fallenbird_age_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bird',
|
||||||
|
name='melden_an_naturschutzbehoerde',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='Melden an Naturschutzbehörde'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bird',
|
||||||
|
name='melden_an_jagdbehoerde',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Melden an Jagdbehörde'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bird',
|
||||||
|
name='melden_an_wildvogelhilfe_team',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='Melden an Wildvogelhilfe-Team'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Data migration to set defaults for existing Bird records
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def set_default_notification_settings(apps, schema_editor):
|
||||||
|
"""Set default notification settings for all existing Bird records."""
|
||||||
|
Bird = apps.get_model('bird', 'Bird')
|
||||||
|
|
||||||
|
# Update all existing birds to have the default notification settings
|
||||||
|
Bird.objects.all().update(
|
||||||
|
melden_an_naturschutzbehoerde=True,
|
||||||
|
melden_an_wildvogelhilfe_team=True,
|
||||||
|
melden_an_jagdbehoerde=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_default_notification_settings(apps, schema_editor):
|
||||||
|
"""Reverse the default settings if needed."""
|
||||||
|
Bird = apps.get_model('bird', 'Bird')
|
||||||
|
|
||||||
|
# Reset all notification settings to False
|
||||||
|
Bird.objects.all().update(
|
||||||
|
melden_an_naturschutzbehoerde=False,
|
||||||
|
melden_an_wildvogelhilfe_team=False,
|
||||||
|
melden_an_jagdbehoerde=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bird', '0007_add_notification_settings'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
set_default_notification_settings,
|
||||||
|
reverse_default_notification_settings
|
||||||
|
),
|
||||||
|
]
|
14
app/bird/migrations/0009_merge_20250609_2033.py
Normal file
14
app/bird/migrations/0009_merge_20250609_2033.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Generated by Django 5.2.2 on 2025-06-09 18:33
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bird', '0007_alter_fallenbird_status'),
|
||||||
|
('bird', '0008_set_default_notification_settings'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
]
|
|
@ -193,6 +193,20 @@ class Bird(models.Model):
|
||||||
updated = models.DateTimeField(
|
updated = models.DateTimeField(
|
||||||
auto_now=True, verbose_name=_("Geändert am")
|
auto_now=True, verbose_name=_("Geändert am")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# New notification settings fields - "Melden an" section
|
||||||
|
melden_an_naturschutzbehoerde = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("Melden an Naturschutzbehörde")
|
||||||
|
)
|
||||||
|
melden_an_jagdbehoerde = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
verbose_name=_("Melden an Jagdbehörde")
|
||||||
|
)
|
||||||
|
melden_an_wildvogelhilfe_team = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("Melden an Wildvogelhilfe-Team")
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Vogel")
|
verbose_name = _("Vogel")
|
||||||
|
|
50
app/bird/templates/bird/bird_species_edit.html
Normal file
50
app/bird/templates/bird/bird_species_edit.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3>E-Mail-Benachrichtigungen für {{ bird_species.name }} bearbeiten</h3>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 mb-3">
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
<a href="{% url 'bird_species_list' %}" class="btn btn-success">Abbrechen</a>
|
||||||
|
<button class="btn btn-primary" type="submit">Speichern</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5>Informationen zu E-Mail-Benachrichtigungen</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h6>Naturschutzbehörde</h6>
|
||||||
|
<p class="small">
|
||||||
|
Wenn aktiviert, wird automatisch eine E-Mail an alle als "Naturschutzbehörde"
|
||||||
|
markierten E-Mail-Adressen gesendet, wenn ein Vogel dieser Art gefunden wird.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h6>Jagdbehörde</h6>
|
||||||
|
<p class="small">
|
||||||
|
Wenn aktiviert, wird automatisch eine E-Mail an alle als "Jagdbehörde"
|
||||||
|
markierten E-Mail-Adressen gesendet, wenn ein Vogel dieser Art gefunden wird.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h6>Wildvogelhilfe-Team</h6>
|
||||||
|
<p class="small">
|
||||||
|
Wenn aktiviert, wird automatisch eine E-Mail an alle als "Wildvogelhilfe-Team"
|
||||||
|
markierten E-Mail-Adressen gesendet, wenn ein Vogel dieser Art gefunden wird.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="alert alert-info mt-3">
|
||||||
|
<strong>Hinweis:</strong> Für neue Vogelarten werden standardmäßig
|
||||||
|
"Naturschutzbehörde" und "Wildvogelhilfe-Team" aktiviert.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
58
app/bird/templates/bird/bird_species_list.html
Normal file
58
app/bird/templates/bird/bird_species_list.html
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3>Vogelarten - E-Mail-Benachrichtigungen verwalten</h3>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 mb-3">
|
||||||
|
<p>
|
||||||
|
Hier können Sie für jede Vogelart konfigurieren, welche Behörden und Teams
|
||||||
|
automatisch benachrichtigt werden sollen, wenn ein Vogel dieser Art gefunden wird.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Vogelart</th>
|
||||||
|
<th>Naturschutzbehörde</th>
|
||||||
|
<th>Jagdbehörde</th>
|
||||||
|
<th>Wildvogelhilfe-Team</th>
|
||||||
|
<th>Aktionen</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for bird in birds %}
|
||||||
|
<tr>
|
||||||
|
<td><strong>{{ bird.name }}</strong></td>
|
||||||
|
<td>
|
||||||
|
{% if bird.melden_an_naturschutzbehoerde %}
|
||||||
|
<span class="badge bg-success">Aktiv</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-secondary">Inaktiv</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if bird.melden_an_jagdbehoerde %}
|
||||||
|
<span class="badge bg-success">Aktiv</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-secondary">Inaktiv</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if bird.melden_an_wildvogelhilfe_team %}
|
||||||
|
<span class="badge bg-success">Aktiv</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-secondary">Inaktiv</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'bird_species_edit' bird.id %}" class="btn btn-sm btn-primary">Bearbeiten</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
|
@ -8,6 +8,8 @@ from .views import (
|
||||||
bird_help_single,
|
bird_help_single,
|
||||||
bird_inactive,
|
bird_inactive,
|
||||||
bird_single,
|
bird_single,
|
||||||
|
bird_species_list,
|
||||||
|
bird_species_edit,
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
@ -17,5 +19,7 @@ urlpatterns = [
|
||||||
path("delete/<id>", bird_delete, name="bird_delete"),
|
path("delete/<id>", bird_delete, name="bird_delete"),
|
||||||
path("help/", bird_help, name="bird_help"),
|
path("help/", bird_help, name="bird_help"),
|
||||||
path("help/<id>", bird_help_single, name="bird_help_single"),
|
path("help/<id>", bird_help_single, name="bird_help_single"),
|
||||||
|
path("species/", bird_species_list, name="bird_species_list"),
|
||||||
|
path("species/<id>/edit/", bird_species_edit, name="bird_species_edit"),
|
||||||
path("<id>/", bird_single, name="bird_single"),
|
path("<id>/", bird_single, name="bird_single"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,11 +7,11 @@ from django.shortcuts import redirect, render, HttpResponse
|
||||||
from django.core.mail import send_mail, BadHeaderError
|
from django.core.mail import send_mail, BadHeaderError
|
||||||
from smtplib import SMTPException
|
from smtplib import SMTPException
|
||||||
|
|
||||||
from .forms import BirdAddForm, BirdEditForm
|
from .forms import BirdAddForm, BirdEditForm, BirdSpeciesForm
|
||||||
from .models import Bird, FallenBird
|
from .models import Bird, FallenBird
|
||||||
|
|
||||||
from sendemail.message import messagebody
|
from sendemail.message import messagebody
|
||||||
from sendemail.models import BirdEmail
|
from sendemail.models import BirdEmail, Emailadress
|
||||||
|
|
||||||
env = environ.Env()
|
env = environ.Env()
|
||||||
|
|
||||||
|
@ -33,24 +33,42 @@ def bird_create(request):
|
||||||
fs.save()
|
fs.save()
|
||||||
request.session["rescuer_id"] = None
|
request.session["rescuer_id"] = None
|
||||||
|
|
||||||
# Send email to all related email addresses
|
# Send email to all related email addresses based on bird species notification settings
|
||||||
email_addresses = BirdEmail.objects.filter(bird=fs.bird_id)
|
|
||||||
bird = Bird.objects.get(id=fs.bird_id)
|
bird = Bird.objects.get(id=fs.bird_id)
|
||||||
try:
|
|
||||||
send_mail(
|
# Get email addresses that match the bird species' notification settings
|
||||||
subject="Wildvogel gefunden!",
|
email_addresses = []
|
||||||
message=messagebody(
|
|
||||||
fs.date_found, bird, fs.place, fs.diagnostic_finding
|
# Check each notification category and add matching email addresses
|
||||||
),
|
if bird.melden_an_naturschutzbehoerde:
|
||||||
from_email=env("DEFAULT_FROM_EMAIL"),
|
naturschutz_emails = Emailadress.objects.filter(is_naturschutzbehoerde=True)
|
||||||
recipient_list=[
|
email_addresses.extend([email.email_address for email in naturschutz_emails])
|
||||||
email.email.email_address for email in email_addresses
|
|
||||||
],
|
if bird.melden_an_jagdbehoerde:
|
||||||
)
|
jagd_emails = Emailadress.objects.filter(is_jagdbehoerde=True)
|
||||||
except BadHeaderError:
|
email_addresses.extend([email.email_address for email in jagd_emails])
|
||||||
return HttpResponse("Invalid header found.")
|
|
||||||
except SMTPException as e:
|
if bird.melden_an_wildvogelhilfe_team:
|
||||||
print("There was an error sending an email: ", e)
|
team_emails = Emailadress.objects.filter(is_wildvogelhilfe_team=True)
|
||||||
|
email_addresses.extend([email.email_address for email in team_emails])
|
||||||
|
|
||||||
|
# Remove duplicates
|
||||||
|
email_addresses = list(set(email_addresses))
|
||||||
|
|
||||||
|
if email_addresses: # Only send if there are recipients
|
||||||
|
try:
|
||||||
|
send_mail(
|
||||||
|
subject="Wildvogel gefunden!",
|
||||||
|
message=messagebody(
|
||||||
|
fs.date_found, bird, fs.place, fs.diagnostic_finding
|
||||||
|
),
|
||||||
|
from_email=env("DEFAULT_FROM_EMAIL"),
|
||||||
|
recipient_list=email_addresses,
|
||||||
|
)
|
||||||
|
except BadHeaderError:
|
||||||
|
return HttpResponse("Invalid header found.")
|
||||||
|
except SMTPException as e:
|
||||||
|
print("There was an error sending an email: ", e)
|
||||||
|
|
||||||
return redirect("bird_all")
|
return redirect("bird_all")
|
||||||
context = {"form": form}
|
context = {"form": form}
|
||||||
|
@ -119,3 +137,26 @@ def bird_delete(request, id):
|
||||||
return redirect("bird_all")
|
return redirect("bird_all")
|
||||||
context = {"bird": bird}
|
context = {"bird": bird}
|
||||||
return render(request, "bird/bird_delete.html", context)
|
return render(request, "bird/bird_delete.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url="account_login")
|
||||||
|
def bird_species_list(request):
|
||||||
|
"""List all bird species with their notification settings."""
|
||||||
|
birds = Bird.objects.all().order_by("name")
|
||||||
|
context = {"birds": birds}
|
||||||
|
return render(request, "bird/bird_species_list.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url="account_login")
|
||||||
|
def bird_species_edit(request, id):
|
||||||
|
"""Edit bird species notification settings."""
|
||||||
|
bird_species = Bird.objects.get(id=id)
|
||||||
|
form = BirdSpeciesForm(request.POST or None, instance=bird_species)
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return redirect("bird_species_list")
|
||||||
|
|
||||||
|
context = {"form": form, "bird_species": bird_species}
|
||||||
|
return render(request, "bird/bird_species_edit.html", context)
|
||||||
|
|
|
@ -233,6 +233,12 @@ STATIC_URL = "static/"
|
||||||
STATICFILES_DIRS = [BASE_DIR / "static"]
|
STATICFILES_DIRS = [BASE_DIR / "static"]
|
||||||
STATIC_ROOT = BASE_DIR / "staticfiles"
|
STATIC_ROOT = BASE_DIR / "staticfiles"
|
||||||
|
|
||||||
|
# -----------------------------------
|
||||||
|
# Media files (User uploaded content)
|
||||||
|
# -----------------------------------
|
||||||
|
MEDIA_URL = "/media/"
|
||||||
|
MEDIA_ROOT = BASE_DIR / "media"
|
||||||
|
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
# Email
|
# Email
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
|
from django.conf import settings
|
||||||
|
from django.conf.urls.static import static
|
||||||
from bird import views
|
from bird import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
@ -14,6 +16,12 @@ urlpatterns = [
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
# Allauth
|
# Allauth
|
||||||
path("accounts/", include("allauth.urls")),
|
path("accounts/", include("allauth.urls")),
|
||||||
|
# CKEditor 5
|
||||||
|
path("ckeditor5/", include('django_ckeditor_5.urls')),
|
||||||
# Static sites
|
# Static sites
|
||||||
# path("", include("sites.urls")),
|
# path("", include("sites.urls")),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Serve media files during development
|
||||||
|
if settings.DEBUG:
|
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
|
@ -5,10 +5,24 @@ from .models import Emailadress, BirdEmail
|
||||||
|
|
||||||
@admin.register(Emailadress)
|
@admin.register(Emailadress)
|
||||||
class EmailaddressAdmin(admin.ModelAdmin):
|
class EmailaddressAdmin(admin.ModelAdmin):
|
||||||
list_display = ["email_address", "created_at", "updated_at", "user"]
|
list_display = ["email_address", "is_naturschutzbehoerde", "is_jagdbehoerde", "is_wildvogelhilfe_team", "created_at", "updated_at", "user"]
|
||||||
search_fields = ["email_address"]
|
search_fields = ["email_address"]
|
||||||
list_filter = ["created_at", "updated_at", "user"]
|
list_filter = ["is_naturschutzbehoerde", "is_jagdbehoerde", "is_wildvogelhilfe_team", "created_at", "updated_at", "user"]
|
||||||
list_per_page = 20
|
list_per_page = 20
|
||||||
|
fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'fields': ('email_address',)
|
||||||
|
}),
|
||||||
|
('Notification Categories', {
|
||||||
|
'fields': ('is_naturschutzbehoerde', 'is_jagdbehoerde', 'is_wildvogelhilfe_team'),
|
||||||
|
'description': 'Select which types of notifications this email address should receive'
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
def save_model(self, request, obj, form, change):
|
||||||
|
if not change: # Only set user when creating new object
|
||||||
|
obj.user = request.user
|
||||||
|
super().save_model(request, obj, form, change)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(BirdEmail)
|
@admin.register(BirdEmail)
|
||||||
|
|
30
app/sendemail/forms.py
Normal file
30
app/sendemail/forms.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from .models import Emailadress
|
||||||
|
|
||||||
|
|
||||||
|
class EmailaddressForm(forms.ModelForm):
|
||||||
|
"""Form for editing email addresses with notification categories."""
|
||||||
|
class Meta:
|
||||||
|
model = Emailadress
|
||||||
|
fields = [
|
||||||
|
"email_address",
|
||||||
|
"is_naturschutzbehoerde",
|
||||||
|
"is_jagdbehoerde",
|
||||||
|
"is_wildvogelhilfe_team",
|
||||||
|
]
|
||||||
|
labels = {
|
||||||
|
"email_address": _("E-Mail-Adresse"),
|
||||||
|
"is_naturschutzbehoerde": _("Naturschutzbehörde"),
|
||||||
|
"is_jagdbehoerde": _("Jagdbehörde"),
|
||||||
|
"is_wildvogelhilfe_team": _("Wildvogelhilfe-Team"),
|
||||||
|
}
|
||||||
|
help_texts = {
|
||||||
|
"is_naturschutzbehoerde": _("Diese Adresse für Naturschutzbehörden-Benachrichtigungen verwenden"),
|
||||||
|
"is_jagdbehoerde": _("Diese Adresse für Jagdbehörden-Benachrichtigungen verwenden"),
|
||||||
|
"is_wildvogelhilfe_team": _("Diese Adresse für Wildvogelhilfe-Team-Benachrichtigungen verwenden"),
|
||||||
|
}
|
||||||
|
widgets = {
|
||||||
|
"email_address": forms.EmailInput(attrs={"class": "form-control"}),
|
||||||
|
}
|
28
app/sendemail/migrations/0002_add_notification_categories.py
Normal file
28
app/sendemail/migrations/0002_add_notification_categories.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated manually for notification categories
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sendemail', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='emailadress',
|
||||||
|
name='is_naturschutzbehoerde',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Naturschutzbehörde'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='emailadress',
|
||||||
|
name='is_jagdbehoerde',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Jagdbehörde'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='emailadress',
|
||||||
|
name='is_wildvogelhilfe_team',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='Wildvogelhilfe-Team'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 5.2.2 on 2025-06-10 06:28
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sendemail', '0002_add_notification_categories'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='emailadress',
|
||||||
|
name='is_naturschutzbehoerde',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='Naturschutzbehörde'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='emailadress',
|
||||||
|
name='is_wildvogelhilfe_team',
|
||||||
|
field=models.BooleanField(default=True, verbose_name='Wildvogelhilfe-Team'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -14,6 +14,20 @@ class Emailadress(models.Model):
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
verbose_name=_("Benutzer"),
|
verbose_name=_("Benutzer"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# New notification category fields
|
||||||
|
is_naturschutzbehoerde = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("Naturschutzbehörde")
|
||||||
|
)
|
||||||
|
is_jagdbehoerde = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
verbose_name=_("Jagdbehörde")
|
||||||
|
)
|
||||||
|
is_wildvogelhilfe_team = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
verbose_name=_("Wildvogelhilfe-Team")
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.email_address
|
return self.email_address
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
<a class="nav-link {% if '/contacts' in request.path %} active {% endif %}"
|
<a class="nav-link {% if '/contacts' in request.path %} active {% endif %}"
|
||||||
href="{% url 'contact_all' %}">Kontakte</a>
|
href="{% url 'contact_all' %}">Kontakte</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link {% if '/bird/species' in request.path %} active {% endif %}"
|
||||||
|
href="{% url 'bird_species_list' %}">Vogelarten</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
{% if request.user|group_check:"data-export" %}
|
{% if request.user|group_check:"data-export" %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
|
|
@ -31,7 +31,8 @@ services:
|
||||||
- db
|
- db
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.django.rule=Host(`${ALLOWED_HOSTS}`)"
|
- "traefik.http.routers.web.rule=Host(`${ALLOWED_HOSTS}`)"
|
||||||
|
- "traefik.http.services.web.loadbalancer.server.port=8000"
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: postgres:15-alpine
|
image: postgres:15-alpine
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue