Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
thalia
concrexit
Commits
80202e60
Commit
80202e60
authored
Sep 12, 2018
by
Thom Wiggers
📐
Browse files
Merge branch 'feature/activemembers-refactor' into 'master'
Added Society model Closes
#635
See merge request
!933
parents
931ceaec
ce7f1c89
Changes
41
Hide whitespace changes
Inline
Side-by-side
website/activemembers/admin.py
View file @
80202e60
...
...
@@ -3,65 +3,48 @@ import csv
import
datetime
from
django
import
forms
from
django.db.models
import
Q
from
django.contrib
import
admin
,
messages
from
django.
contrib.auth
.models
import
Permission
from
django.
db
.models
import
Q
from
django.http
import
HttpResponse
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
activemembers
import
models
from
activemembers.forms
import
CommitteeMembershipForm
from
utils.translation
import
TranslatedModelAdmin
from
activemembers.forms
import
MemberGroupMembershipForm
,
MemberGroupForm
from
utils.snippets
import
datetime_to_lectureyear
from
utils.translation
import
TranslatedModelAdmin
class
Committee
MembershipInlineFormSet
(
forms
.
BaseInlineFormSet
):
class
MemberGroup
MembershipInlineFormSet
(
forms
.
BaseInlineFormSet
):
"""
Solely here for performance reasons.
Needed because the `__str__()` of `
Committee
Membership` (which is displayed
Needed because the `__str__()` of `
MemberGroup
Membership` (which is displayed
above each inline form) uses the username, name of the member and name of
the
committee
.
the
group
.
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
().
__init__
(
*
args
,
**
kwargs
)
self
.
queryset
=
self
.
queryset
.
select_related
(
'member'
,
'
committee
'
).
filter
(
until
=
None
)
'member'
,
'
group
'
).
filter
(
until
=
None
)
class
Committee
MembershipInline
(
admin
.
StackedInline
):
"""Inline for
committee
memberships"""
model
=
models
.
Committee
Membership
formset
=
Committee
MembershipInlineFormSet
class
MemberGroup
MembershipInline
(
admin
.
StackedInline
):
"""Inline for
group
memberships"""
model
=
models
.
MemberGroup
Membership
formset
=
MemberGroup
MembershipInlineFormSet
can_delete
=
False
ordering
=
(
'since'
,)
extra
=
0
autocomplete_fields
=
(
'member'
,)
class
CommitteeForm
(
forms
.
ModelForm
):
"""
Solely here for performance reasons.
Needed because the `__str__()` of `Permission` (which is displayed in the
permissions selection box) also prints the corresponding app and
`content_type` for each permission.
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
().
__init__
(
*
args
,
**
kwargs
)
self
.
fields
[
'permissions'
].
queryset
=
(
Permission
.
objects
.
select_related
(
'content_type'
))
@
admin
.
register
(
models
.
Committee
)
class
CommitteeAdmin
(
TranslatedModelAdmin
):
"""Manage the committees"""
inlines
=
(
Committee
MembershipInline
,)
form
=
Committee
Form
inlines
=
(
MemberGroup
MembershipInline
,)
form
=
MemberGroup
Form
list_display
=
(
'name'
,
'since'
,
'until'
,
'active'
,
'email'
)
list_filter
=
(
'until'
,
'active'
,)
search_fields
=
(
'name'
,
'description'
)
...
...
@@ -78,16 +61,33 @@ class CommitteeAdmin(TranslatedModelAdmin):
return
instance
.
contact_mailinglist
.
name
+
'@thalia.nu'
return
None
def
get_queryset
(
self
,
request
):
qs
=
super
().
get_queryset
(
request
)
return
qs
.
exclude
(
board__is_board
=
True
)
@
admin
.
register
(
models
.
Society
)
class
CommitteeAdmin
(
TranslatedModelAdmin
):
"""Manage the societies"""
inlines
=
(
MemberGroupMembershipInline
,)
form
=
MemberGroupForm
list_display
=
(
'name'
,
'since'
,
'until'
,
'active'
,
'email'
)
list_filter
=
(
'until'
,
'active'
,)
search_fields
=
(
'name'
,
'description'
)
filter_horizontal
=
(
'permissions'
,)
fields
=
(
'name'
,
'description'
,
'photo'
,
'permissions'
,
'since'
,
'until'
,
'contact_mailinglist'
,
'contact_email'
,
'active'
)
def
email
(
self
,
instance
):
if
instance
.
contact_email
:
return
instance
.
contact_email
elif
instance
.
contact_mailinglist
:
return
instance
.
contact_mailinglist
.
name
+
'@thalia.nu'
return
None
@
admin
.
register
(
models
.
Board
)
class
BoardAdmin
(
TranslatedModelAdmin
):
"""Manage the board"""
inlines
=
(
Committee
MembershipInline
,)
form
=
Committee
Form
inlines
=
(
MemberGroup
MembershipInline
,)
form
=
MemberGroup
Form
exclude
=
(
'is_board'
,)
filter_horizontal
=
(
'permissions'
,)
...
...
@@ -95,22 +95,25 @@ class BoardAdmin(TranslatedModelAdmin):
'contact_mailinglist'
,
'contact_email'
,
'since'
,
'until'
,)
class
Board
Filter
(
admin
.
SimpleListFilter
):
class
Type
Filter
(
admin
.
SimpleListFilter
):
"""Filter memberships on board-only"""
title
=
_
(
'
board
memberships'
)
parameter_name
=
'
board
'
title
=
_
(
'
group
memberships'
)
parameter_name
=
'
group_type
'
def
lookups
(
self
,
request
,
model_admin
):
return
[
(
'only'
,
_
(
'Only board memberships'
)),
(
'none'
,
_
(
'No board memberships'
)),
(
'boards'
,
_
(
'Only boards'
)),
(
'committees'
,
_
(
'Only committees'
)),
(
'societies'
,
_
(
'Only societies'
)),
]
def
queryset
(
self
,
request
,
queryset
):
if
self
.
value
()
==
'only'
:
return
queryset
.
filter
(
committee__board__is_board
=
True
)
elif
self
.
value
()
==
'none'
:
return
queryset
.
exclude
(
committee__board__is_board
=
True
)
if
self
.
value
()
==
'boards'
:
return
queryset
.
exclude
(
group__board
=
None
)
elif
self
.
value
()
==
'committees'
:
return
queryset
.
exclude
(
group__committee
=
None
)
elif
self
.
value
()
==
'societies'
:
return
queryset
.
exclude
(
group__society
=
None
)
return
queryset
...
...
@@ -123,7 +126,7 @@ class LectureYearFilter(admin.SimpleListFilter):
def
lookups
(
self
,
request
,
model_admin
):
current_year
=
datetime_to_lectureyear
(
timezone
.
now
())
first_year
=
datetime_to_lectureyear
(
models
.
Committee
Membership
.
objects
.
earliest
(
'since'
).
since
models
.
MemberGroup
Membership
.
objects
.
earliest
(
'since'
).
since
)
return
[(
year
,
'{}-{}'
.
format
(
year
,
year
+
1
))
...
...
@@ -161,14 +164,14 @@ class ActiveMembershipsFilter(admin.SimpleListFilter):
return
queryset
.
filter
(
until__lt
=
now
)
@
admin
.
register
(
models
.
Committee
Membership
)
class
Committee
MembershipAdmin
(
TranslatedModelAdmin
):
"""Manage the
committee
memberships"""
form
=
Committee
MembershipForm
list_display
=
(
'member'
,
'
committee
'
,
'since'
,
'until'
,
'chair'
,
'role'
)
list_filter
=
(
'
committee'
,
Board
Filter
,
LectureYearFilter
,
@
admin
.
register
(
models
.
MemberGroup
Membership
)
class
MemberGroup
MembershipAdmin
(
TranslatedModelAdmin
):
"""Manage the
group
memberships"""
form
=
MemberGroup
MembershipForm
list_display
=
(
'member'
,
'
group
'
,
'since'
,
'until'
,
'chair'
,
'role'
)
list_filter
=
(
'
group'
,
Type
Filter
,
LectureYearFilter
,
ActiveMembershipsFilter
)
list_select_related
=
(
'member'
,
'
committee
'
,)
list_select_related
=
(
'member'
,
'
group
'
,)
search_fields
=
(
'member__first_name'
,
'member__last_name'
,
'member__email'
)
...
...
@@ -176,8 +179,8 @@ class CommitteeMembershipAdmin(TranslatedModelAdmin):
def
changelist_view
(
self
,
request
,
extra_context
=
None
):
self
.
message_user
(
request
,
_
(
'Do not edit existing memberships if the '
'chair of a
committee
has changed, add a '
'new
committee
membership instead.'
),
'chair of a
group
has changed, add a '
'new membership instead.'
),
messages
.
WARNING
)
return
super
().
changelist_view
(
request
,
extra_context
)
...
...
@@ -185,16 +188,16 @@ class CommitteeMembershipAdmin(TranslatedModelAdmin):
response
=
HttpResponse
(
content_type
=
'text/csv'
)
response
[
'Content-Disposition'
]
=
(
'attachment;'
'filename='
'"
committee
_memberships.csv"'
)
'"
group
_memberships.csv"'
)
writer
=
csv
.
writer
(
response
)
writer
.
writerow
([
_
(
'First name'
),
_
(
'Last name'
),
_
(
'Email'
),
_
(
'
Committee
'
),
_
(
'
Committee m
ember since'
),
_
(
'
Committee m
ember until'
),
_
(
'Chair of the
committee
'
),
_
(
'
Group
'
),
_
(
'
M
ember since'
),
_
(
'
M
ember until'
),
_
(
'Chair of the
group
'
),
_
(
'Role'
),
])
...
...
@@ -203,7 +206,7 @@ class CommitteeMembershipAdmin(TranslatedModelAdmin):
membership
.
member
.
first_name
,
membership
.
member
.
last_name
,
membership
.
member
.
email
,
membership
.
committee
,
membership
.
group
,
membership
.
since
,
membership
.
until
,
membership
.
chair
,
...
...
website/activemembers/backends.py
View file @
80202e60
...
...
@@ -8,8 +8,8 @@ from django.utils import timezone
from
members.models
import
Member
class
Committee
Backend
(
object
):
"""Check permissions against
committee
s"""
class
MemberGroup
Backend
(
object
):
"""Check permissions against
MemberGroup
s"""
def
authenticate
(
self
,
*
args
,
**
kwargs
):
"""Not implemented in this backend"""
...
...
@@ -27,15 +27,15 @@ class CommitteeBackend(object):
except
Member
.
DoesNotExist
:
return
set
()
committee
s
=
member
.
committee
_set
.
filter
(
Q
(
committee
membership__until
=
None
)
|
Q
(
committee
membership__until__gte
=
timezone
.
now
())
group
s
=
member
.
membergroup
_set
.
filter
(
Q
(
membergroup
membership__until
=
None
)
|
Q
(
membergroup
membership__until__gte
=
timezone
.
now
())
)
perm_cache_name
=
'_
committee
_perm_cache'
perm_cache_name
=
'_
membergroup
_perm_cache'
if
not
hasattr
(
user
,
perm_cache_name
):
perms
=
(
Permission
.
objects
.
filter
(
committee__in
=
committee
s
)
.
filter
(
membergroup__in
=
group
s
)
.
values_list
(
'content_type__app_label'
,
'codename'
)
.
order_by
())
setattr
(
user
,
perm_cache_name
,
...
...
website/activemembers/fixtures/
committee
s.json
→
website/activemembers/fixtures/
member_group
s.json
View file @
80202e60
[
{
"model"
:
"activemembers.
committee
"
,
"model"
:
"activemembers.
membergroup
"
,
"pk"
:
1
,
"fields"
:
{
"name_nl"
:
"testcie1"
,
...
...
@@ -17,7 +17,7 @@
}
},
{
"model"
:
"activemembers.
committee
"
,
"model"
:
"activemembers.
membergroup
"
,
"pk"
:
2
,
"fields"
:
{
"name_nl"
:
"testcie2"
,
...
...
@@ -30,7 +30,7 @@
}
},
{
"model"
:
"activemembers.
committee
"
,
"model"
:
"activemembers.
membergroup
"
,
"pk"
:
3
,
"fields"
:
{
"name_nl"
:
"testbestuur1"
,
...
...
@@ -42,11 +42,41 @@
"until"
:
"1991-09-01"
}
},
{
"model"
:
"activemembers.membergroup"
,
"pk"
:
4
,
"fields"
:
{
"name_nl"
:
"testsoc1"
,
"name_en"
:
"testsoc1"
,
"active"
:
"True"
,
"description_nl"
:
"testdesc1"
,
"description_en"
:
"testdesc1"
,
"since"
:
"1990-09-01"
,
"until"
:
"1991-09-01"
}
},
{
"model"
:
"activemembers.committee"
,
"pk"
:
1
,
"fields"
:
{
}
},
{
"model"
:
"activemembers.committee"
,
"pk"
:
2
,
"fields"
:
{
}
},
{
"model"
:
"activemembers.board"
,
"pk"
:
3
,
"fields"
:
{
"is_board"
:
true
}
},
{
"model"
:
"activemembers.society"
,
"pk"
:
4
,
"fields"
:
{
}
}
]
website/activemembers/forms.py
View file @
80202e60
"""The forms defined by the activemembers module"""
from
django
import
forms
from
django.contrib.auth.models
import
Permission
from
activemembers.models
import
Committee
Membership
from
activemembers.models
import
MemberGroup
Membership
from
members.models
import
Member
class
Committee
MembershipForm
(
forms
.
ModelForm
):
"""Custom form for
committee
memberships that orders the members"""
class
MemberGroup
MembershipForm
(
forms
.
ModelForm
):
"""Custom form for
group
memberships that orders the members"""
member
=
forms
.
ModelChoiceField
(
queryset
=
Member
.
objects
.
order_by
(
'first_name'
,
'last_name'
))
class
Meta
:
model
=
Committee
Membership
model
=
MemberGroup
Membership
exclude
=
()
class
MemberGroupForm
(
forms
.
ModelForm
):
"""
Solely here for performance reasons.
Needed because the `__str__()` of `Permission` (which is displayed in the
permissions selection box) also prints the corresponding app and
`content_type` for each permission.
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
().
__init__
(
*
args
,
**
kwargs
)
self
.
fields
[
'permissions'
].
queryset
=
(
Permission
.
objects
.
select_related
(
'content_type'
))
website/activemembers/locale/nl/LC_MESSAGES/django.mo
View file @
80202e60
No preview for this file type
website/activemembers/locale/nl/LC_MESSAGES/django.po
View file @
80202e60
...
...
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-0
7-11 20:07
+0200\n"
"PO-Revision-Date: 2018-0
6-13 20:08
+0200\n"
"POT-Creation-Date: 2018-0
9-06 16:13
+0200\n"
"PO-Revision-Date: 2018-0
9-06 16:12
+0200\n"
"Last-Translator: Sébastiaan Versteeg <se_bastiaan@outlook.com>\n"
"Language-Team: \n"
"Language: nl\n"
...
...
@@ -16,245 +16,274 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.
6
\n"
"X-Generator: Poedit 2.0.
4
\n"
#: a
ctivemembers/admin
.py
msgid "
board
memberships"
msgstr "
bestuur
slidmaatschappen"
#: a
dmin.py models
.py
msgid "
group
memberships"
msgstr "
groep
slidmaatschappen"
#:
activemembers/
admin.py
msgid "Only board
membership
s"
msgstr "Alleen bestu
urslidmaatschapp
en"
#: admin.py
msgid "Only boards"
msgstr "Alleen bestu
r
en"
#:
activemembers/
admin.py
msgid "
No board membership
s"
msgstr "
G
een
bestuurslidmaatschappen
"
#: admin.py
msgid "
Only committee
s"
msgstr "
All
een
commissies
"
#: activemembers/admin.py
#: admin.py
msgid "Only societies"
msgstr "Alleen gezelschappen"
#: admin.py
msgid "lecture year"
msgstr "collegejaar"
#:
activemembers/
admin.py
#: admin.py
msgid "active memberships"
msgstr "actieve lidmaatschappen"
#:
activemembers/
admin.py
#: admin.py
msgid "Active"
msgstr "Actief"
#:
activemembers/
admin.py
#: admin.py
msgid "Inactive"
msgstr "Inactief"
#:
activemembers/
admin.py
#: admin.py
msgid ""
"Do not edit existing memberships if the chair of a
committee
has changed, "
"
add a new committee
membership instead."
"Do not edit existing memberships if the chair of a
group
has changed,
add a
"
"
new
membership instead."
msgstr ""
"Pas geen bestaande lidmaatschappen aan als de voorzitter van een
commissie
"
"
is
veranderd. Voeg in de plaats daarvan een nieuw commissielidmaatschap toe."
"Pas geen bestaande lidmaatschappen aan als de voorzitter van een
groep is
"
"veranderd. Voeg in de plaats daarvan een nieuw commissielidmaatschap toe."
#:
activemembers/
admin.py
#: admin.py
msgid "First name"
msgstr "Voornaam"
#:
activemembers/
admin.py
#: admin.py
msgid "Last name"
msgstr "Achernaam"
#:
activemembers/
admin.py
#: admin.py
msgid "Email"
msgstr "Email"
#: a
ctivemembers/admin.py activemembers/models
.py
msgid "
Committee
"
msgstr "
Commissie
"
#: a
dmin
.py
msgid "
Group
"
msgstr "
Groep
"
#: a
ctivemembers/admin.py activemembers/
models.py
msgid "
Committee m
ember since"
msgstr "
Commissiel
id sinds"
#: a
dmin.py
models.py
msgid "
M
ember since"
msgstr "
L
id sinds"
#: a
ctivemembers/admin.py activemembers/
models.py
msgid "
Committee m
ember until"
msgstr "
Commissiel
id tot"
#: a
dmin.py
models.py
msgid "
M
ember until"
msgstr "
L
id tot"
#: a
ctivemembers/admin.py activemembers/models
.py
msgid "Chair of the
committee
"
msgstr "Voorzitter van de
commissie
"
#: a
dmin
.py
msgid "Chair of the
group
"
msgstr "Voorzitter van de
groep
"
#:
activemembers/
admin.py
#: admin.py
msgid "Role"
msgstr "Rol"
#:
activemembers/
admin.py
#: admin.py
msgid "Export selected memberships"
msgstr "Exporteer de geselecteerde lidmaatschappen"
#:
activemembers/
apps.py
#: apps.py
msgid "Active members"
msgstr "Actieve leden"
#:
activemembers/
models.py
#: models.py
msgid "Committee name"
msgstr "Commissienaam"
#:
activemembers/
models.py
#: models.py
msgid "Description"
msgstr "Beschrijving"
#:
activemembers/
models.py
#: models.py
msgid "Image"
msgstr "Afbeelding"
#:
activemembers/
models.py
#: models.py
msgid "permissions"
msgstr "permissies"
#:
activemembers/
models.py
#: models.py
msgid "founded in"
msgstr "opgericht in"
#:
activemembers/
models.py
#: models.py
msgid "existed until"
msgstr "bestond tot"
#:
activemembers/
models.py
#: models.py
msgid "contact email address"
msgstr "contact e-mailadres"
#:
activemembers/
models.py
#: models.py
msgid "contact mailing list"
msgstr "contact mailinglijst"
#: activemembers/models.py
msgid "Wiki namespace"
msgstr "Wiki namespace"
#: activemembers/models.py
#: models.py
msgid "Please use either the mailing list or email address option."
msgstr "Selecteer een mailinglijst óf vul een e-mailadres in."
#: activemembers/models.py
#: models.py
msgid "member group"
msgstr "ledengroep"
#: models.py
msgid "member groups"
msgstr "ledengroepen"
#: models.py
msgid "Wiki namespace"
msgstr "Wiki namespace"
#: models.py
msgid "committee"
msgstr "commissie"
#: activemembers/models.py
#: activemembers/templates/activemembers/committee_index.html
#: models.py templates/activemembers/committee_index.html
msgid "committees"
msgstr "commissies"
#: activemembers/models.py
msgid "Is this a board"
msgstr "Is dit een bestuur"
#: models.py
msgid "society"
msgstr "gezelschap"
#: models.py templates/activemembers/society_detail.html
#: templates/activemembers/society_index.html
msgid "societies"
msgstr "gezelschappen"
#: models.py
msgid "board"
msgstr "bestuur"
#: activemembers/models.py
#: models.py
msgid "boards"
msgstr "besturen"
#: models.py
msgid "Access the board wiki"
msgstr "Toegang tot bestuurswiki"
#:
activemembers/
models.py
#: models.py
msgid "A board already exists for those years"
msgstr "Er bestaat al een bestuur voor die jaren"
#:
activemembers/
models.py
#: models.py
msgid "Member"
msgstr "Lid"
#: activemembers/models.py
msgid "The date this member joined the committee in this role"
msgstr "De datum waarop deze persoon lid werd deze commissie in deze rol"
#: models.py
msgid "Committee"
msgstr "Commissie"
#: models.py
msgid "The date this member joined in this role"
msgstr "De datum waarop deze persoon lid werd in deze rol"
#:
activemembers/
models.py
msgid "A member
of this committee
until this time (can't be in the future)."
#: models.py
msgid "A member until this time (can't be in the future)."