Merge branch 'main' into MK/group_overview

pull/118/head
mariusrklein 11 months ago
commit 7e48e00e96

@ -0,0 +1,4 @@
[report]
omit =
./jet/*
manage.py

@ -1,7 +1,10 @@
from unittest import skip
from django.test import TestCase
from django.utils import timezone
from django.conf import settings
from .models import Statement, StatementUnSubmitted, StatementSubmitted, Bill, Ledger, Transaction
from .models import Statement, StatementUnSubmitted, StatementSubmitted, Bill, Ledger, Transaction,\
StatementUnSubmittedManager, StatementSubmittedManager, StatementConfirmedManager,\
StatementConfirmed, TransactionIssue, StatementManager
from members.models import Member, Group, Freizeit, GEMEINSCHAFTS_TOUR, MUSKELKRAFT_ANREISE, NewMemberOnList,\
FAHRGEMEINSCHAFT_ANREISE, MALE, FEMALE, DIVERSE
@ -11,6 +14,7 @@ class StatementTestCase(TestCase):
kilometers_traveled = 512
participant_count = 10
staff_count = 5
allowance_to_count = 3
def setUp(self):
self.jl = Group.objects.create(name="Jugendleiter")
@ -49,7 +53,7 @@ class StatementTestCase(TestCase):
amount=42.69, costs_covered=True, paid_by=m)
m.group.add(self.jl)
ex.jugendleiter.add(m)
if i < 3:
if i < self.allowance_to_count:
self.st3.allowance_to.add(m)
ex = Freizeit.objects.create(name='Wild trip 2', kilometers_traveled=self.kilometers_traveled,
@ -165,6 +169,18 @@ class StatementTestCase(TestCase):
self.assertFalse(self.st2.transactions_match_expenses,
'Transactions match expenses, but one transaction was tweaked.')
def test_generate_transactions_not_covered(self):
bill = self.st2.bill_set.all()[0]
bill.paid_by = None
bill.save()
self.st2.generate_transactions()
self.assertTrue(self.st2.transactions_match_expenses)
bill.amount = 0
bill.paid_by = self.fritz
bill.save()
self.assertTrue(self.st2.transactions_match_expenses)
def test_statement_without_excursion(self):
# should be all 0, since no excursion is associated
self.assertEqual(self.st.real_staff_count, 0)
@ -192,3 +208,153 @@ class StatementTestCase(TestCase):
# so statement must be invalid
self.assertFalse(self.st.is_valid(),
'Transaction is valid, although an unreasonable gift is paid.')
@skip('This fails on main, but will be resolved when #112 is merged.')
def test_allowance_to_valid(self):
self.assertEqual(self.st3.excursion.participant_count, self.participant_count)
# st3 should have 3 admissible yls and all of them should receive allowance
self.assertEqual(self.st3.admissible_staff_count, self.allowance_to_count)
self.assertEqual(self.st3.allowances_paid, self.allowance_to_count)
self.assertTrue(self.st3.allowance_to_valid)
m1 = self.st3.excursion.jugendleiter.all()[0]
m2 = self.st3.excursion.jugendleiter.all()[self.allowance_to_count]
# now remove one, so allowance_to should be reduced by one
self.st3.allowance_to.remove(m1)
self.assertEqual(self.st3.allowances_paid, self.allowance_to_count - 1)
# but still valid
self.assertTrue(self.st3.allowance_to_valid)
# and theoretical staff costs are now higher than real staff costs
self.assertLess(self.st3.total_staff, self.st3.theoretical_total_staff)
self.assertLess(self.st3.real_per_yl, self.st3.total_per_yl)
# adding a foreign yl adds the number of allowances_paid
self.st3.allowance_to.add(self.fritz)
self.assertEqual(self.st3.allowances_paid, self.allowance_to_count)
# but invalidates `allowance_to`
self.assertFalse(self.st3.allowance_to_valid)
# remove the foreign yl and add too many yls
self.st3.allowance_to.remove(self.fritz)
self.st3.allowance_to.add(m1, m2)
self.assertEqual(self.st3.allowances_paid, self.allowance_to_count + 1)
# should be invalid
self.assertFalse(self.st3.allowance_to_valid)
self.st3.generate_transactions()
for trans in self.st3.transaction_set.all():
trans.ledger = self.personal_account
trans.save()
self.assertEqual(self.st3.validity, Statement.INVALID_ALLOWANCE_TO)
def test_total_pretty(self):
self.assertEqual(self.st3.total_pretty(), "{}".format(self.st3.total))
def test_template_context(self):
# with excursion
self.assertTrue('euro_per_km' in self.st3.template_context())
# without excursion
self.assertFalse('euro_per_km' in self.st2.template_context())
def test_grouped_bills(self):
bills = self.st2.grouped_bills()
self.assertTrue('amount' in bills[0])
class LedgerTestCase(TestCase):
def setUp(self):
self.personal_account = Ledger.objects.create(name='personal account')
def test_str(self):
self.assertTrue(str(self.personal_account), 'personal account')
class ManagerTestCase(TestCase):
def setUp(self):
self.st = Statement.objects.create(short_description='A statement',
explanation='Important!',
night_cost=0)
self.st_submitted = Statement.objects.create(short_description='A statement',
explanation='Important!',
night_cost=0,
submitted=True)
self.st_confirmed = Statement.objects.create(short_description='A statement',
explanation='Important!',
night_cost=0,
confirmed=True)
def test_get_queryset(self):
# TODO: remove this manager, since it is not used
mgr = StatementManager()
mgr.model = Statement
self.assertQuerysetEqual(mgr.get_queryset(), Statement.objects.filter(pk=self.st.pk))
mgr_unsubmitted = StatementUnSubmittedManager()
mgr_unsubmitted.model = StatementUnSubmitted
self.assertQuerysetEqual(mgr_unsubmitted.get_queryset(), Statement.objects.filter(pk=self.st.pk))
mgr_submitted = StatementSubmittedManager()
mgr_submitted.model = StatementSubmitted
self.assertQuerysetEqual(mgr_submitted.get_queryset(), Statement.objects.filter(pk=self.st_submitted.pk))
mgr_confirmed = StatementConfirmedManager()
mgr_confirmed.model = StatementConfirmed
self.assertQuerysetEqual(mgr_confirmed.get_queryset(), Statement.objects.filter(pk=self.st_confirmed.pk))
class TransactionTestCase(TestCase):
def setUp(self):
self.st = Statement.objects.create(short_description='A statement',
explanation='Important!',
night_cost=0)
self.personal_account = Ledger.objects.create(name='personal account')
self.fritz = Member.objects.create(prename="Fritz", lastname="Wulter", birth_date=timezone.now().date(),
email=settings.TEST_MAIL, gender=MALE)
self.trans = Transaction.objects.create(reference='foobar',
amount=42,
member=self.fritz,
ledger=self.personal_account,
statement=self.st)
def test_str(self):
self.assertTrue(str(self.trans.pk) in str(self.trans))
def test_escape_reference(self):
self.assertEqual(Transaction.escape_reference('harmless'), 'harmless')
self.assertEqual(Transaction.escape_reference('äöüÄÖÜß'), 'aeoeueAeOeUess')
self.assertEqual(Transaction.escape_reference('ha@r!?mless+09'), 'har?mless+09')
def test_code(self):
self.trans.amount = 0
# amount is zero, so empty
self.assertEqual(self.trans.code(), '')
self.trans.amount = 42
# iban is invalid, so empty
self.assertEqual(self.trans.code(), '')
# a valid (random) iban
self.fritz.iban = 'DE89370400440532013000'
self.assertNotEqual(self.trans.code(), '')
class BillTestCase(TestCase):
def setUp(self):
self.st = Statement.objects.create(short_description='A statement',
explanation='Important!',
night_cost=0)
self.bill = Bill.objects.create(statement=self.st,
short_description='foobar')
def test_str(self):
self.assertTrue('' in str(self.bill))
def test_pretty_amount(self):
self.assertTrue('' in self.bill.pretty_amount())
class TransactionIssueTestCase(TestCase):
def setUp(self):
self.issue = TransactionIssue('foo', 42, 26)
def test_difference(self):
self.assertEqual(self.issue.difference, 26 - 42)

@ -284,7 +284,7 @@ msgstr "Zu Gruppe einladen"
#: templates/nesting/admin/inlines/stacked.html
#, python-format
msgid "Add another %(verbose_name)s"
msgstr "Weiteren %(verbose_name)s hinzufügen"
msgstr "%(verbose_name)s hinzufügen"
#: utils.py
msgid "Please keep filesize under {} MiB. Current filesize: {:10.2f} MiB."

@ -1085,9 +1085,10 @@ class GenerateSjrForm(forms.Form):
class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin):
#inlines = [MemberOnListInline, LJPOnListInline, StatementOnListInline]
form = FreizeitAdminForm
list_display = ['__str__', 'date']
list_display = ['__str__', 'date', 'place']
search_fields = ('name',)
ordering = ('-date',)
list_filter = ['groups']
view_on_site = False
fieldsets = (
(None, {

@ -1609,7 +1609,7 @@ msgstr "Weiteren hinzufügen"
#, python-format
msgid "I am already or will become a member of the DAV %(sektion)s soon."
msgstr ""
"Ich bin bereits Mitglied der DAV %(sektion)s, oder beantrage die "
"Ich bin bereits Mitglied des DAV %(sektion)s, oder beantrage die "
"Mitgliedschaft zeitnah."
#: members/templates/members/member_form.html
@ -1856,20 +1856,21 @@ msgstr ""
#: members/views.py
msgid "Prename of the member."
msgstr "Vorname des Teilnehmenden"
msgstr "Vorname des*der Teilnehmenden"
#: members/views.py
msgid "Lastname of the member."
msgstr "Nachname des Teilnehmenden"
msgstr "Nachname des*der Teilnehmenden"
#: members/views.py
msgid "phone number of child or parent"
msgstr "Telefonnummer des Teilnehmenden oder einer Kontaktperson"
msgstr "Telefonnummer des*der Teilnehmenden oder einer Kontaktperson"
#: members/views.py
msgid "email of child if available, otherwise parental email address"
msgstr ""
"Falls verfügbar, E-Mailadresse des Teilnehmenden, sonst einer Kontaktperson"
"Falls verfügbar, E-Mailadresse des*der Teilnehmenden, sonst einer "
"Kontaktperson"
#: members/views.py
msgid "optional additional email address"

@ -5,6 +5,8 @@ from django.contrib.auth import models as authmodels
from django.contrib.admin.sites import AdminSite
from django.contrib.messages import get_messages
from django.contrib.auth.models import User
from django.contrib import admin
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from django.test import TestCase, Client, RequestFactory
from django.utils import timezone, translation
@ -14,9 +16,11 @@ from django import template
from unittest import skip, mock
from .models import Member, Group, PermissionMember, PermissionGroup, Freizeit, GEMEINSCHAFTS_TOUR, MUSKELKRAFT_ANREISE,\
MemberNoteList, NewMemberOnList, confirm_mail_by_key, EmergencyContact, MemberWaitingList,\
RegistrationPassword, MemberUnconfirmedProxy, InvitationToGroup, DIVERSE, MALE, FEMALE
RegistrationPassword, MemberUnconfirmedProxy, InvitationToGroup, DIVERSE, MALE, FEMALE,\
Klettertreff, KlettertreffAttendee
from .admin import MemberWaitingListAdmin, MemberAdmin, FreizeitAdmin, MemberNoteListAdmin,\
MemberUnconfirmedAdmin
MemberUnconfirmedAdmin, RegistrationFilter, FilteredMemberFieldMixin,\
MemberAdminForm, StatementOnListForm, KlettertreffAdmin, GroupAdmin
from .pdf import fill_pdf_form, render_tex, media_path, serve_pdf, find_template, merge_pdfs
from mailer.models import EmailAddress
from finance.models import Statement, Bill
@ -331,6 +335,7 @@ class MemberAdminTestCase(AdminTestCase):
m.group.add(mega_kids)
m.save()
self.fritz = cool_kids.member_set.first()
self.peter = mega_kids.member_set.first()
def test_changelist(self):
c = self._login('superuser')
@ -454,21 +459,95 @@ class MemberAdminTestCase(AdminTestCase):
c = self._login('superuser')
response = c.post(reverse('admin:members_member_inviteasuser', args=(12345,)))
self.assertEqual(response.status_code, HTTPStatus.FOUND)
# expect: user does not exist
response = c.post(reverse('admin:members_member_inviteasuser', args=(12345,)), follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Member not found.'))
response = c.post(url)
self.assertEqual(response.status_code, HTTPStatus.FOUND)
# expect: user is found, but email address is not internal
response = c.post(url, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertFalse(self.fritz.has_internal_email())
self.assertContains(response,
_("The configured email address for %(name)s is not an internal one.") % {'name': str(self.fritz)})
# update email to allowed email domain
self.fritz.email = 'foobar@{domain}'.format(domain=settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0])
self.fritz.save()
response = c.post(url)
# expect: user is found and confirmation page is shown
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Invite'))
# expect: user is invited
response = c.post(url, data={'apply': ''})
self.assertEqual(response.status_code, HTTPStatus.FOUND)
# expect: user already has a pending invitation
response = c.post(url)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response,
_('%(name)s already has a pending invitation as user.' % {'name': str(self.fritz)}))
# set user
u = User.objects.create(username='fritzuser', password='secret')
self.fritz.user = u
self.fritz.save()
# expect: user already has an account
response = c.post(url, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _("%(name)s already has login data.") % {'name': str(self.fritz)})
def test_invite_as_user_action(self):
qs = Member.objects.all()
url = reverse('admin:members_member_changelist')
# expect: confirmation view
c = self._login('superuser')
response = c.post(url, data={'action': 'invite_as_user_action',
'_selected_action': [self.fritz.pk]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Invite'))
# confirm invite, expect: partial success
response = c.post(url, data={'action': 'invite_as_user_action',
'_selected_action': [self.fritz.pk], 'apply': True}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Some members have been invited, others could not be invited.'))
# confirm invite, expect: success
self.peter.email = 'foobar@{domain}'.format(domain=settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0])
self.peter.save()
self.fritz.email = 'foobar@{domain}'.format(domain=settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0])
self.fritz.save()
response = c.post(url, data={'action': 'invite_as_user_action',
'_selected_action': [self.fritz.pk, self.peter.pk], 'apply': True}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Successfully invited selected members to join as users.'))
def test_send_mail_to(self):
# this is not connected to an action currently
qs = Member.objects.all()
response = self.admin.send_mail_to(None, qs)
self.assertEqual(response.status_code, HTTPStatus.FOUND)
def test_request_echo(self):
self.peter.gets_newsletter = False
self.peter.save()
url = reverse('admin:members_member_changelist')
# expect: success
c = self._login('superuser')
response = c.post(url, data={'action': 'request_echo',
'_selected_action': [self.fritz.pk, self.peter.pk]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
def test_activity_score(self):
# manually set activity score
for i in range(5):
self.fritz._activity_score = i * 10 - 1
self.assertTrue('img' in self.admin.activity_score(self.fritz))
class FreizeitTestCase(BasicMemberTestCase):
@ -1399,3 +1478,221 @@ class EchoViewTestCase(BasicMemberTestCase):
))
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, _('Your data was successfully updated.'))
class TestRegistrationFilterTestCase(AdminTestCase):
def setUp(self):
super().setUp(model=Member, admin=MemberAdmin)
def test_lookups(self):
fil = RegistrationFilter(None, {}, Member, self.admin)
self.assertTrue(('All', _('All')) in fil.lookups(None, None))
def test_queryset_no_filter(self):
qs = Member.objects.all()
# filtering with All returns passed queryset
fil = RegistrationFilter(None, {'registration_complete': 'All'}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs), qs, ordered=False)
# or with None
fil = RegistrationFilter(None, {}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs), qs, ordered=False)
@skip("Currently errors, because 'registration_complete' is not a field.")
def test_queryset_filter(self):
qs = Member.objects.all()
fil = RegistrationFilter(None, {'registration_complete': 'True'}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs),
Member.objects.filter(registration_complete=True),
ordered=False)
fil = RegistrationFilter(None, {'registration_complete': 'False'}, Member, self.admin)
self.assertQuerysetEqual(fil.queryset(None, qs),
Member.objects.filter(registration_complete=True),
ordered=False)
fil = RegistrationFilter(None, {}, Member, self.admin)
fil.default_value = ('True', True)
self.assertQuerysetEqual(fil.queryset(None, qs),
Member.objects.filter(registration_complete=True),
ordered=False)
class MemberAdminFormTestCase(TestCase):
def test_clean_iban(self):
form_data = dict(REGISTRATION_DATA, iban='foobar')
form = MemberAdminForm(data=form_data)
self.assertTrue('IBAN' in str(form.errors))
form_data = dict(REGISTRATION_DATA, iban='DE89370400440532013000')
form = MemberAdminForm(data=form_data)
self.assertFalse('IBAN' in str(form.errors))
class StatementOnListFormTestCase(BasicMemberTestCase):
def setUp(self):
super().setUp()
self.ex = Freizeit.objects.create(name='Wild trip', kilometers_traveled=120,
tour_type=GEMEINSCHAFTS_TOUR,
tour_approach=MUSKELKRAFT_ANREISE,
difficulty=1)
self.ex.jugendleiter.add(self.fritz)
self.ex.save()
self.st = Statement.objects.create(excursion=self.ex, night_cost=42, subsidy_to=None)
self.st.allowance_to.add(self.fritz)
self.st.save()
def test_clean(self):
form = StatementOnListForm(parent_obj=self.ex, instance=self.st)
# should not raise any error
form.cleaned_data = {'excursion': self.ex,
'allowance_to': None}
form.clean()
# should raise Validation error because too many allowance_to are listed
form.cleaned_data = {'excursion': self.ex,
'allowance_to': Member.objects.filter(pk=self.fritz.pk)}
self.assertGreater(1, self.ex.approved_staff_count)
self.assertRaises(ValidationError, form.clean)
class KlettertreffAdminTestCase(AdminTestCase):
def setUp(self):
super().setUp(model=Klettertreff, admin=KlettertreffAdmin)
cool_kids = Group.objects.get(name='cool kids')
for i in range(10):
kl = Klettertreff.objects.create(location='foo', topic='bar', group=cool_kids)
def test_change(self):
kl = Klettertreff.objects.first()
url = reverse('admin:members_klettertreff_change', args=(kl.pk,))
c = self._login('superuser')
response = c.get(url)
self.assertEqual(response.status_code, HTTPStatus.OK)
def test_overview(self):
qs = Klettertreff.objects.all()
url = reverse('admin:members_klettertreff_changelist')
# expect: success
c = self._login('superuser')
response = c.post(url, data={'action': 'overview',
'_selected_action': [kl.pk for kl in qs]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
# expect: success and filtered by group, this does not work
c = self._login('superuser')
response = c.post(url, data={'action': 'overview',
'group__name': 'cool kids',
'_selected_action': [kl.pk for kl in qs]}, follow=True)
self.assertEqual(response.status_code, HTTPStatus.OK)
class GroupAdminTestCase(AdminTestCase):
def setUp(self):
super().setUp(model=Group, admin=GroupAdmin)
def test_change(self):
g = Group.objects.first()
url = reverse('admin:members_group_change', args=(g.pk,))
c = self._login('superuser')
response = c.get(url)
self.assertEqual(response.status_code, HTTPStatus.OK)
class FilteredMemberFieldMixinTestCase(AdminTestCase):
def setUp(self):
class CustomGroupAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
class CustomMemberAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
class CustomMemberAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
class CustomKlettertreffAttendeeAdmin(FilteredMemberFieldMixin, admin.ModelAdmin):
pass
self.custom_gr_admin = CustomGroupAdmin(Group, AdminSite())
self.custom_member_admin = CustomMemberAdmin(Member, AdminSite())
self.custom_kla_admin = CustomKlettertreffAttendeeAdmin(KlettertreffAttendee, AdminSite())
super().setUp(model=Group, admin=CustomGroupAdmin)
User.objects.create_user(
username='foobar', password='secret'
)
def test_invalid_manytomany(self):
# filtering a db_field with related model != Member should return the db_field unchanged
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
request.user = User.objects.get(username='superuser')
db_field = Member._meta.get_field('group')
member_admin = MemberAdmin(Member, AdminSite())
self.assertQuerysetEqual(self.custom_member_admin.formfield_for_manytomany(db_field, request).queryset,
member_admin.formfield_for_manytomany(db_field, request).queryset,
ordered=False)
def test_invalid_foreignkey(self):
# filtering a db_field with related model != Member should return the db_field unchanged
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
request.user = User.objects.get(username='superuser')
db_field = Group._meta.get_field('contact_email')
gr_admin = GroupAdmin(Group, AdminSite())
self.assertQuerysetEqual(self.admin.formfield_for_foreignkey(db_field, request).queryset,
gr_admin.formfield_for_foreignkey(db_field, request).queryset)
def test_filter_manytomany(self):
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
# if user has `members.list_global_member`, the filter returns all fields
request.user = User.objects.get(username='superuser')
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), request)
self.assertQuerysetEqual(field.queryset,
Member.objects.all(),
ordered=False)
# if not, it is filtered by permissions
u = User.objects.get(username='standard')
request.user = u
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), request)
self.assertQuerysetEqual(field.queryset,
u.member.filter_queryset_by_permissions(model=Member),
ordered=False)
# if no request is passed, no members are shown
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), None)
self.assertQuerysetEqual(field.queryset, Member.objects.none())
# if user has no associated member and does not have the special permission,
# the filter returns nothing
request.user = User.objects.get(username='foobar')
field = self.admin.formfield_for_manytomany(Group._meta.get_field('leiters'), request)
self.assertQuerysetEqual(field.queryset, Member.objects.none(), ordered=False)
def test_filter_foreignkey(self):
url = reverse('admin:members_memberwaitinglist_changelist')
request = self.factory.get(url)
# if user has `members.list_global_member`, the filter returns all fields
request.user = User.objects.get(username='superuser')
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), request)
self.assertQuerysetEqual(field.queryset,
Member.objects.all(),
ordered=False)
# if not, it is filtered by permissions
u = User.objects.get(username='standard')
request.user = u
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), request)
self.assertQuerysetEqual(field.queryset,
u.member.filter_queryset_by_permissions(model=Member),
ordered=False)
# if no request is passed, no members are shown
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), None)
self.assertQuerysetEqual(field.queryset, Member.objects.none())
# if user has no associated member and does not have the special permission,
# the filter returns nothing
request.user = User.objects.get(username='foobar')
field = self.admin.formfield_for_foreignkey(KlettertreffAttendee._meta.get_field('member'), request)
self.assertQuerysetEqual(field.queryset, Member.objects.none(), ordered=False)

@ -90,7 +90,7 @@ msgstr "Bilder"
#: startpage/models.py
msgid "Member"
msgstr "Mitglied"
msgstr "Teilnehmer*in"
#: startpage/models.py
msgid "Description"

Loading…
Cancel
Save