From 8288ee8766c2687750262ff92019fbf5c44c0eac Mon Sep 17 00:00:00 2001 From: Patrick Date: Sun, 23 Aug 2020 18:00:49 +0000 Subject: [PATCH] update members templates and views members layout is not finished --- fet2020/fet2020/urls.py | 2 +- fet2020/members/admin.py | 10 +- fet2020/members/forms.py | 2 +- fet2020/members/models.py | 178 ++++++++---------- fet2020/members/urls.py | 7 +- fet2020/members/views.py | 46 +++-- fet2020/templates/layout.html | 2 +- fet2020/templates/members/index.html | 107 ++++------- fet2020/templates/members/jobs_list.html | 26 +++ fet2020/templates/members/list.html | 30 --- fet2020/templates/members/members_list.html | 26 +++ .../members/partials/_member_details.html | 8 +- fet2020/templates/members/show_job.html | 28 --- 13 files changed, 196 insertions(+), 276 deletions(-) create mode 100644 fet2020/templates/members/jobs_list.html delete mode 100644 fet2020/templates/members/list.html create mode 100644 fet2020/templates/members/members_list.html delete mode 100644 fet2020/templates/members/show_job.html diff --git a/fet2020/fet2020/urls.py b/fet2020/fet2020/urls.py index cd376bf8..fb8164f1 100644 --- a/fet2020/fet2020/urls.py +++ b/fet2020/fet2020/urls.py @@ -34,5 +34,5 @@ urlpatterns = [ path('index.html', views.index, name='home'), path('ckeditor/', include('ckeditor_uploader.urls')), path('api/', include(router.urls)), - path('members/', include('members.urls')), + path('members/', include('members.urls'), name='members'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/fet2020/members/admin.py b/fet2020/members/admin.py index ef324319..5042ca5d 100644 --- a/fet2020/members/admin.py +++ b/fet2020/members/admin.py @@ -16,10 +16,8 @@ class MemberRoleFilter(admin.SimpleListFilter): ) def queryset(self, request, queryset): - if self.value() == 'A': - return queryset.filter(role='A') - elif self.value() == 'P': - return queryset.filter(role='P') + if self.value() in Member.MemberRole: + return queryset.filter(role=self.value()) class JobMemberInline(admin.TabularInline): @@ -37,7 +35,7 @@ class ActiveMemberInline(JobMemberInline): verbose_name_plural = "Aktive Mitglieder Liste" def get_queryset(self, request): - return JobMember.active_member.all() + return JobMember.active_member.get_all() class InactiveMemberInline(JobMemberInline): @@ -45,7 +43,7 @@ class InactiveMemberInline(JobMemberInline): verbose_name_plural = "Inaktive Mitglieder Liste" def get_queryset(self, request): - return JobMember.inactive_member.all() + return JobMember.inactive_member.get_all() class JobInline(admin.TabularInline): diff --git a/fet2020/members/forms.py b/fet2020/members/forms.py index 2e6927ae..5f90b632 100644 --- a/fet2020/members/forms.py +++ b/fet2020/members/forms.py @@ -45,4 +45,4 @@ class MyJobForm(forms.ModelForm): class MyJobGroupForm(forms.ModelForm): class Meta: model = JobGroup - fields = ['name', 'shortterm', 'is_pinned'] + fields = ['name', 'shortterm', 'slug', 'is_pinned'] diff --git a/fet2020/members/models.py b/fet2020/members/models.py index df3bea85..5ba8ea43 100644 --- a/fet2020/members/models.py +++ b/fet2020/members/models.py @@ -4,45 +4,78 @@ from django.db.models import Q from django.utils import timezone from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ -from rest_framework import serializers - -# import uuid from datetime import timedelta +from rest_framework import serializers -class MemberManager(models.Manager): - def get_queryset(self): - return super().get_queryset().filter(role='A') +class MemberQuerySet(models.QuerySet): + def get_members(self): + date_today = timezone.now().date() + return self.filter( + Q(member__role=Member.MemberRole.ACTIVE) + & (Q(job_end__gt=date_today) | Q(job_end__isnull=True)) + ) -class PensionManager(models.Manager): - def get_queryset(self): - return super().get_queryset().filter(role='P') + def get_inactive(self): + date_today = timezone.now().date() + + return self.filter( + Q(member__role=Member.MemberRole.PENSION) + | (Q(job_end__lt=date_today + timedelta(days=1)) & Q(job_end__isnull=False)) + ) class ActiveMemberManager(models.Manager): ''' return a list of active member, and members who are still working ''' - def get_queryset(self): - date_today = timezone.now().date() + def get_members_of_job(self, job_names): + tmp_list = [] + for job_name in job_names: + tmp_list.append(self.get_queryset().get_members().filter(Q(job__name=job_name))) + return tmp_list - return super().get_queryset().filter( - Q(member__role='A') - & (Q(job_end__gt=date_today) | Q(job_end__isnull=True))) + def get_all(self): + return self.get_queryset().get_members() + + def get_queryset(self): + return MemberQuerySet(self.model, using=self._db) class InactiveMemberManager(models.Manager): ''' return a list of inactive member ''' - def get_queryset(self): - date_today = timezone.now().date() + def get_members_of_job(self, job_names): + tmp_list = [] + for job_name in job_names: + tmp_list.append(self.get_queryset().get_inactive().filter(Q(job__name=job_name))) + return tmp_list - return super().get_queryset().filter( - Q(member__role='P') - | (Q(job_end__lt=date_today + timedelta(days=1)) & Q(job_end__isnull=False))) + def get_all(self): + return self.get_queryset().get_inactive() + + def get_queryset(self): + return MemberQuerySet(self.model, using=self._db) + + +class MemberManager(models.Manager): + def get_members(self, role): + return self.get_queryset().filter(Q(member__role=role)) + + def get_all(self): + return self.get_queryset() + + +class JobManager(models.Manager): + def get_job_names(self, slug): + tmp_list = [] + for i in self.get_queryset().filter(Q(job__job_group__slug=slug)): + if i.job.name not in tmp_list: + tmp_list.append(i.job.name) + return tmp_list class Member(models.Model): @@ -51,13 +84,11 @@ class Member(models.Model): nickname = models.CharField(max_length=128) mailaccount = models.CharField(max_length=128) - __choices = [ - ('A', _('Active')), - ('P', _('Pension')), - ] - role = models.CharField(max_length=1, choices=__choices, default='A') - - role_choices=[c[0] for c in __choices] # Letter from choices + class MemberRole(models.TextChoices): + ACTIVE = 'A', _('Active') + PENSION = 'P', _('Pension') + + role = models.CharField(max_length=1, choices=MemberRole.choices, default=MemberRole.ACTIVE) description = models.TextField(null=True, blank=True) image = models.ImageField(null=True, blank=True) @@ -65,18 +96,10 @@ class Member(models.Model): birthday = models.DateField(null=True, blank=True) phone_error_msg = _(( - "Phone number must be entered in the format: " - "+999999999'. Up to 15 digits allowed." + "Phone number must be entered in the format: +999999999'. Up to 15 digits allowed." )) - phone_regex = RegexValidator( - regex=r'^\+?1?\d{9,15}$', - message=phone_error_msg, - ) - phone = models.CharField( - validators=[phone_regex], - max_length=17, - blank=True, - ) + phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message=phone_error_msg) + phone = models.CharField(validators=[phone_regex], max_length=17, blank=True) address = models.TextField(null=True, blank=True) @@ -85,13 +108,7 @@ class Member(models.Model): # Managers all_members = models.Manager() - active_member = MemberManager() - pension_member = PensionManager() - - @property - def all_jobs(self): - return [j.job for j in self.jobs.all()] - + class Meta: verbose_name = "Mitglied" verbose_name_plural = "Mitglieder" @@ -117,6 +134,9 @@ class MemberSerializer(serializers.HyperlinkedModelSerializer): class JobGroup(models.Model): name = models.CharField(max_length=128) shortterm = models.CharField(max_length=128) + + slug = models.SlugField(unique=True, null=True, blank=True) + is_pinned = models.BooleanField(default=False) def __str__(self): @@ -131,40 +151,13 @@ class Job(models.Model): description = models.TextField(null=True, blank=True) image = models.ImageField(null=True, blank=True) - #objects = models.Manager() + job_group = models.ForeignKey( JobGroup, on_delete=models.CASCADE, verbose_name="Job Gruppe", ) - @property - def active_members(self): - "Active Members for this job" - date_today = timezone.now().date() - def sorted_jobmembers(): - return sorted(list(self.jobmembers.filter(Q(member__role ='A') & - (Q(job_end__gt=date_today) | Q(job_end__isnull=True))).all()), # filter active fehlt noch - key=lambda x: (JobMember._role_sort[x.job_role], JobMember.job_start)) - m =[jm.member_with_role for jm in sorted_jobmembers()] - - return m - - @property - def active_members_count(self): - "Count Active Members" - date_today = timezone.now().date() - return self.jobmembers.filter(Q(member__role ='A') & - (Q(job_end__gt=date_today) | Q(job_end__isnull=True))).count() - - @property - def inactive_members(self): - "return the inactive members" - date_today = timezone.now().date() - return [jm.member for jm in self.jobmembers.filter(~Q(member__role ='A') | - (Q(job_end__lt=date_today) & Q(job_end__isnull=False))).all()] # filter inactive fehlt noch - - class Meta: verbose_name = "Tätigkeit" verbose_name_plural = "Tätigkeiten" @@ -184,47 +177,28 @@ class JobMember(models.Model): Member, on_delete=models.CASCADE, verbose_name="Mitglied", - related_name="jobs" ) job = models.ForeignKey( Job, on_delete=models.CASCADE, verbose_name="Tätigkeit", - related_name="jobmembers" ) job_start = models.DateField('Job Start') job_end = models.DateField('Job Ende', null=True, blank=True) - @property - def member_with_role(self): - "return the member with added role and job start and job end" - m=self.member - m.job_start=self.job_start - m.job_end=self.job_end - m.job_role=self.job_role - m.job_role_text=dict(JobMember._choices)[self.job_role] - return m + class JobRole(models.TextChoices): + PRESIDENT = '1V', _('VorsitzendeR') + VICE_PRESIDENT = '2V', _('stv VorsitzendeR') + SECOND_VICE_PRESIDENT = '3V', _('2. stv VorsitzendeR') + MEMBER = 'M', _('Mitglied') + SUBSTITUTE_MEMBER = 'E', _('Ersatzmitglied') + PERSON_RESPONSIBLE = 'V', _('VerantwortlicheR') - _choices = [ - ('1V', _('VorsitzendeR')), - ('2V', _('stv VorsitzendeR')), - ('3V', _('2. stv VorsitzendeR')), - ('M', _('Mitglied')), - ('E', _('Ersatzmitglied')), - ('V', _('VerantwortlicheR')) - ] - _role_sort = { - '1V': 1, - '2V': 2, - '3V': 3, - '4V': 4, - 'M':5, - 'E':6, - 'V':7 - } - job_role = models.CharField(max_length=2, choices=_choices, default='M') + job_role = models.CharField(max_length=2, choices=JobRole.choices, default=JobRole.MEMBER) - jobmember = models.Manager() + members = MemberManager() active_member = ActiveMemberManager() inactive_member = InactiveMemberManager() + + jobs = JobManager() diff --git a/fet2020/members/urls.py b/fet2020/members/urls.py index 23305340..9a379aa5 100644 --- a/fet2020/members/urls.py +++ b/fet2020/members/urls.py @@ -4,8 +4,7 @@ from . import views urlpatterns = [ - path('', views.index, name='members.index'), - path('list', views.list, name='members.list'), - path('list/', views.list, name='members.list'), - path('', views.show_job, name='members.show_job') + path('', views.index, name='members'), + path('', views.index), + path('jobs/', views.index), ] diff --git a/fet2020/members/views.py b/fet2020/members/views.py index 5a892b76..be26658b 100644 --- a/fet2020/members/views.py +++ b/fet2020/members/views.py @@ -3,43 +3,41 @@ from django.shortcuts import render from collections import deque -from .models import Member, Job, JobMember, JobGroup, MemberSerializer +from .models import Member, JobMember, JobGroup, MemberSerializer from rest_framework import viewsets from rest_framework import permissions # from django_filters.rest_framework import DjangoFilterBackend -def index(request): - # members = deque(Member.all_members.all()) - members = deque(Member.all_members.all()) - jobmembers = deque(JobMember.jobmember.all()) - jobs = deque(Job.objects.all()) - jobgroups = deque(JobGroup.objects.all()) +def index(request, slug=None, filter=None): + job_group = deque(JobGroup.objects.all()) + job_list = [] + members = None + + if slug is not None: + job_names = JobMember.jobs.get_job_names(slug=slug) + active_members = JobMember.active_member.get_members_of_job(job_names=job_names) + inactive_members = JobMember.inactive_member.get_members_of_job(job_names=job_names) + + for idx, item in enumerate(job_names): + job_list.append((job_names[idx], active_members[idx], inactive_members[idx])) + else: + if filter is None: + members = deque(Member.all_members.all()) + elif filter in Member.MemberRole: + members = deque(Member.all_members.filter(role=filter)) + else: + members = None context = { + "job_group": job_group, + "job_list": job_list, "members": members, - "jobmembers": jobmembers, - "jobgroups": jobgroups, - "jobs": jobs, } return render(request, 'members/index.html', context) -def show_job(request, slug=None): - job=Job.objects.get(slug=slug) - return render(request, 'members/show_job.html', {"job": job}) - -def list(request, filter=None): - """ - View for a list of members filtered or not - """ - if filter is None: - members = deque(Member.all_members.all()) - if filter in Member.role_choices: - members=deque(Member.all_members.filter(role=filter).all()) - - return render(request, 'members/list.html',{"members": members}) class MemberViewSet(viewsets.ModelViewSet): """ diff --git a/fet2020/templates/layout.html b/fet2020/templates/layout.html index f4f2cb9f..f98c89bf 100644 --- a/fet2020/templates/layout.html +++ b/fet2020/templates/layout.html @@ -23,7 +23,7 @@
  • Aktuelles
  • Fotos
  • -
  • Mitarbeiter +
  • Mitarbeiter
  • diff --git a/fet2020/templates/members/index.html b/fet2020/templates/members/index.html index c96e94b3..7e4faf19 100644 --- a/fet2020/templates/members/index.html +++ b/fet2020/templates/members/index.html @@ -1,89 +1,46 @@ {% extends 'layout.html' %} {% block content %} +
    - -Aktive Mitglieder - -{% for job in jobs %} - -{{job.name}} - -{% endfor %} +

    Mitglieder / Tätigkeiten

    + + -
    -
    -

    Members

    - {% for m in members %} -
    - {% if m.image %} -
    + + +
    -
    + {% endblock %} diff --git a/fet2020/templates/members/jobs_list.html b/fet2020/templates/members/jobs_list.html new file mode 100644 index 00000000..23ddb329 --- /dev/null +++ b/fet2020/templates/members/jobs_list.html @@ -0,0 +1,26 @@ + +
    + +Aktuelle Mitglieder: {{active_members.count}} +
    + {% for mem in active_members %} +
    +

    {{mem.get_job_role_display}} (seit {{mem.job_start}})

    + {% with member=mem.member %} + {% include 'members/partials/_member_details.html' %} + {% endwith %} +
    + {% endfor %} +
    + +Vergangene Mitglieder: {{inactive_members.count}} +
    + {% for mem in inactive_members %} +
    +

    {{mem.get_job_role_display}} ({{mem.job_start}} - {{mem.job_end}})

    + {% with member=mem.member %} + {% include 'members/partials/_member_details.html' %} + {% endwith %} +
    + {% endfor %} +
    diff --git a/fet2020/templates/members/list.html b/fet2020/templates/members/list.html deleted file mode 100644 index 8b77add9..00000000 --- a/fet2020/templates/members/list.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} - -
    -

    Mitarbeiter Liste

    -

    Grid Style

    -
    -{% for member in members %} -
    - {% include 'members/partials/_member.html' %} -
    -{% endfor %} -
    - -

    Grid Style 2

    -
    -{% for member in members %} - {% include 'members/partials/_member.html' %} -{% endfor %} -
    - -

    Detail List

    -
    -{% for member in members %} - {% include 'members/partials/_member_details.html' %} -{% endfor %} -
    - -{% endblock %} diff --git a/fet2020/templates/members/members_list.html b/fet2020/templates/members/members_list.html new file mode 100644 index 00000000..b238a7b0 --- /dev/null +++ b/fet2020/templates/members/members_list.html @@ -0,0 +1,26 @@ + +
    +

    Mitarbeiter Liste

    +

    Grid Style

    +
    + {% for member in members %} +
    + {% include 'members/partials/_member.html' %} +
    + {% endfor %} +
    + +

    Grid Style 2

    +
    + {% for member in members %} + {% include 'members/partials/_member.html' %} + {% endfor %} +
    + +

    Detail List

    +
    + {% for member in members %} + {% include 'members/partials/_member_details.html' %} + {% endfor %} +
    +
    diff --git a/fet2020/templates/members/partials/_member_details.html b/fet2020/templates/members/partials/_member_details.html index 854fbc4f..821333f9 100644 --- a/fet2020/templates/members/partials/_member_details.html +++ b/fet2020/templates/members/partials/_member_details.html @@ -9,9 +9,9 @@

    {{member.firstname}} {{member.surname}}

    Spitzname: {{member.nickname}}
    -Name: {{member.firstname}} {{member.surname}}
    -Mailaccount: {{member.mailaccount}}
    -Beschreibung: {{member.description|safe}}
    -

    + Name: {{member.firstname}} {{member.surname}}
    + Mailaccount: {{member.mailaccount}}
    + Beschreibung: {{member.description|safe}}
    +

    diff --git a/fet2020/templates/members/show_job.html b/fet2020/templates/members/show_job.html deleted file mode 100644 index b8eec95d..00000000 --- a/fet2020/templates/members/show_job.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} -
    -
    - -

    {{job.name}}

    -
    - -Aktuelle Mitglieder {{ job.active_members_count}}: -
    -{% for member in job.active_members %} -
    - -

    {{ member.job_role_text }}({{member.job_start }} - {{member.job_end}})

    - {% include 'members/partials/_member_details.html' %} -
    -{% endfor %} - -
    - -Vergangene Mitglieder: -
    -{% for member in job.inactive_members %} - {% include 'members/partials/_member.html' %} -{% endfor %} -
    -{% endblock %}