• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

d120 / pyfeedback / 25237229969

01 May 2026 11:14PM UTC coverage: 88.833% (-0.8%) from 89.664%
25237229969

push

github

4-dash
minor fiexs

2991 of 3367 relevant lines covered (88.83%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.01
/src/feedback/admin.py
1
# coding=utf-8
2

3
from django.contrib import admin
1✔
4
from django import forms
1✔
5
from django.http.response import HttpResponseRedirect
1✔
6
from django.shortcuts import render
1✔
7
from django.utils.translation import gettext_lazy as _
1✔
8

9
from feedback.models import Person, Veranstaltung, Semester, \
1✔
10
    Mailvorlage, Kommentar, Tutor, BarcodeScanner, BarcodeScannEvent, BarcodeAllowedState, \
11
    EmailEndung, Fragebogen2020, FragebogenUE2020, Ergebnis2020, Fragebogen2016, FragebogenUE2016, Ergebnis2016, \
12
    Fragebogen2025, FragebogenUE2025, Ergebnis2025, EmailChange
13
from feedback.models.base import Log, Fachgebiet, FachgebietEmail
1✔
14

15

16
class PersonAdmin(admin.ModelAdmin):
1✔
17
    """Admin View für Personen"""
18
    list_display = ('__str__', 'email', 'fachgebiet')
1✔
19
    search_fields = ['vorname', 'nachname', 'email', ]
1✔
20
    list_filter = ('fachgebiet',)
1✔
21

22
    class FachgebietZuweisenForm(forms.Form):
1✔
23
        """Form für die Zuweisung von einem Fachgebiet für eine Person."""
24
        _selected_action = forms.CharField(widget=forms.MultipleHiddenInput)
1✔
25

26
    def assign_fachgebiet_action(self, request, queryset):
1✔
27
        """Definiert eine Admin-Action für die Fachgebietzuweisung."""
28
        form = None
1✔
29
        suggestion_list = []
1✔
30

31
        for p in queryset:
1✔
32
            proposed_fachgebiet = Fachgebiet.get_fachgebiet_from_email(p.email)
1✔
33
            suggestion_list.append((p, proposed_fachgebiet))
1✔
34

35
        if any(s in request.POST for s in ('apply', 'save')):
1✔
36
            form = self.FachgebietZuweisenForm(request.POST)
1✔
37

38
            if form.is_valid():
1✔
39
                selected_persons = request.POST.getlist("selectedPerson")
1✔
40
                for person in queryset:
1✔
41
                    person_id_str = str(person.id)
1✔
42
                    if person_id_str in selected_persons:
1✔
43
                        proposed_fachgebiet_id = request.POST.get("fachgebiet_" + person_id_str, 0)
1✔
44
                        if int(proposed_fachgebiet_id) > 0:
1✔
45
                            proposed_fachgebiet = Fachgebiet.objects.get(id=proposed_fachgebiet_id)
1✔
46
                            person.fachgebiet = proposed_fachgebiet
1✔
47
                            person.save()
1✔
48
                            suggestion_list = [(x, y) for x, y in suggestion_list if x is not person]
1✔
49

50
                self.message_user(request, _("Fachgebiete erfolgreich zugewiesen."))
1✔
51

52
                if ('save' in request.POST) or not suggestion_list:
1✔
53
                    return HttpResponseRedirect(request.get_full_path())
1✔
54

55
        if not form:
1✔
56
            form = self.FachgebietZuweisenForm(initial={
1✔
57
                '_selected_action': queryset.values_list('id', flat=True)
58
            })
59

60
        return render(request, 'admin/fachgebiet.html', {'data': suggestion_list, 'fachgebiet': form, })
1✔
61

62
    assign_fachgebiet_action.short_description = _("Einem Fachgebiet zuweisen")
1✔
63
    actions = [assign_fachgebiet_action]
1✔
64

65

66
class LogInline(admin.TabularInline):
1✔
67
    """Admin View für Log"""
68
    model = Log
1✔
69
    readonly_fields = ('veranstaltung', 'user', 'scanner', 'timestamp', 'status', 'interface')
1✔
70
    can_delete = False
1✔
71

72
    def has_add_permission(self, request, obj=None):
1✔
73
        return False
×
74

75

76
class VeranstaltungAdmin(admin.ModelAdmin):
1✔
77
    """Admin View für Veranstaltung"""
78
    fieldsets = [
1✔
79
        (_('Stammdaten'), {'fields':
80
                        ['typ', 'name', 'semester', 'status', 'lv_nr', 'grundstudium', 'evaluieren',
81
                         'veranstalter', 'link_veranstalter',
82
                         ]}),
83
        (_('Bestellung'), {'fields': ['sprache', 'anzahl', 'digitale_eval', 'digitale_eval_type', 'verantwortlich', 'ergebnis_empfaenger', 'primaerdozent',
84
                                   'auswertungstermin', 'freiefrage1', 'freiefrage2', 'kleingruppen', ]}),
85
    ]
86
    list_display = ('typ', 'name', 'semester', 'grundstudium', 'evaluieren', 'anzahl',
1✔
87
                    'sprache', 'status', 'veranstalter_list', 'digitale_eval', 'auswertungstermin')
88
    list_display_links = ['name']
1✔
89
    list_filter = ('typ', 'semester', 'status', 'grundstudium', 'evaluieren', 'sprache', 'digitale_eval', 'digitale_eval_type')
1✔
90
    search_fields = ['name']
1✔
91
    filter_horizontal = ('veranstalter', 'ergebnis_empfaenger')  # @see http://stackoverflow.com/a/5386871
1✔
92
    readonly_fields = ('link_veranstalter',)
1✔
93
    inlines = [LogInline, ]
1✔
94

95
    def save_model(self, request, obj, form, change):
1✔
96
        """Definiert eine Post-Save Operation."""
97
        super(VeranstaltungAdmin, self).save_model(request, obj, form, change)
×
98
        for changed_att in form.changed_data:
×
99
            # Wenn sich der Status ändert, wird es geloggt.
100
            if changed_att == "status":
×
101
                obj.log(request.user)
×
102

103
    class StatusAendernForm(forms.Form):
1✔
104
        """Definiert eine Form für Änderung einen Status'."""
105
        _selected_action = forms.CharField(widget=forms.MultipleHiddenInput)
1✔
106
        status = forms.ChoiceField(choices=Veranstaltung.STATUS_CHOICES)
1✔
107

108
    def status_aendern_action(self, request, queryset):
1✔
109
        """Beschreibt eine Admin-Action für die Statusänderung."""
110
        form = None
1✔
111

112
        if 'apply' in request.POST:
1✔
113
            form = self.StatusAendernForm(request.POST)
1✔
114

115
            if form.is_valid():
1✔
116
                status = form.cleaned_data['status']
1✔
117

118
                queryset.update(status=status)
1✔
119
                for veranstaltung in queryset:
1✔
120
                    veranstaltung.log(request.user)
1✔
121

122
                self.message_user(request, _("Status erfolgreich geändert."))
1✔
123
                return HttpResponseRedirect(request.get_full_path())
1✔
124

125
        if not form:
1✔
126
            form = self.StatusAendernForm(initial={'_selected_action': queryset.values_list('id', flat=True)})
1✔
127

128
        return render(request, 'admin/status_aendern.html', {'veranstaltungen': queryset, 'status': form, })
1✔
129

130
    status_aendern_action.short_description = _("Ändere den Status einer Veranstaltung")
1✔
131

132
    class KeineEvaluationForm(forms.Form):
1✔
133
        _selected_action = forms.CharField(widget=forms.MultipleHiddenInput)
1✔
134

135
    def keine_evaluation_action(self, request, queryset):
1✔
136
        """Beschreibt eine Admin-Action für die Option keine Evaluation."""
137
        form = None
×
138

139
        # Dieser Teil reicht bereits zum ändern aus. In diesem Fall können auch Zeile 146-149 gelöscht werden (Kein Bestätigungsfenster erscheint.
140
        if 'apply' in request.POST:
×
141
            queryset.update(status=Veranstaltung.STATUS_KEINE_EVALUATION_FINAL)
×
142
            queryset.update(evaluieren=False)
×
143
            for veranstaltung in queryset:
×
144
                veranstaltung.log(request.user)
×
145

146
            self.message_user(request, _("Veranstaltungen wurden erfolgreich auf Keine Evaluation gesetzt."))
×
147
            return HttpResponseRedirect(request.get_full_path())
×
148
            # nach dem return landet Python in status_aendern_action
149
        if not form:
×
150
            form = self.KeineEvaluationForm(initial={'_selected_action': queryset.values_list('id', flat=True)})
×
151
        return render(request, 'admin/keine_evaluation.html', {'veranstaltungen': queryset, 'status': form, })
×
152

153
    keine_evaluation_action.short_description = _("Keine Evaluation für diese Veranstaltung(en)")
1✔
154

155
    actions = [status_aendern_action, keine_evaluation_action]
1✔
156

157

158
class SemesterAdmin(admin.ModelAdmin):
1✔
159
    """Admin View für Semester"""
160
    list_display = ('__str__', 'sichtbarkeit', 'fragebogen')
1✔
161
    list_filter = ('sichtbarkeit', 'fragebogen')
1✔
162
    ordering = ('-semester',)
1✔
163

164

165
class MailvorlageAdmin(admin.ModelAdmin):
1✔
166
    """Admin View für Mailvorlage"""
167
    list_display = ('subject',)
1✔
168

169

170
class KommentarAdmin(admin.ModelAdmin):
1✔
171
    """Admin View für Kommentar"""
172
    list_display = ('typ', 'name', 'semester', 'autor')
1✔
173
    list_display_links = ('name',)
1✔
174

175

176
class TutorAdmin(admin.ModelAdmin):
1✔
177
    """Admin View für Tutor"""
178
    fieldsets = [
1✔
179
        (_('Stammdaten'), {'fields':
180
                        ['vorname', 'nachname', 'email',
181
                         ]}),
182
        (_('Lehrveranstaltung'), {'fields':
183
                               ['veranstaltung', 'nummer', 'anmerkung'
184
                                ]}),
185
    ]
186
    list_display = ('vorname', 'nachname', 'nummer', 'veranstaltung')
1✔
187
    search_fields = ('vorname', 'nachname')
1✔
188
    ordering = ('veranstaltung', 'nummer')
1✔
189

190
    def render_change_form(self, request, context, *args, **kwargs):
1✔
191
        # Limit Auswahl zum aktuellen Semester
192
        context['adminform'].form.fields['veranstaltung'].queryset = Veranstaltung.objects.filter(
×
193
            semester=Semester.current())
194
        return super(TutorAdmin, self).render_change_form(request, context, args, kwargs)
×
195

196

197
class BarcodeScannEventAdmin(admin.ModelAdmin):
1✔
198
    """Admin View für BarcodeScannEvent"""
199
    list_display = ('veranstaltung', 'timestamp',)
1✔
200
    readonly_fields = ('veranstaltung', 'timestamp',)
1✔
201

202

203
class BarcodeAllowedStateInline(admin.TabularInline):
1✔
204
    """Admin View für BarcodeAllowedState"""
205
    model = BarcodeAllowedState
1✔
206

207

208
class BarcodeScannerAdmin(admin.ModelAdmin):
1✔
209
    """Admin View für BarcodeScanner"""
210
    inlines = [
1✔
211
        BarcodeAllowedStateInline,
212
    ]
213
    list_display = ('token', 'description')
1✔
214

215

216
class FachgebietEmailAdminInline(admin.TabularInline):
1✔
217
    """Admin View für FachgebietEmail"""
218
    model = FachgebietEmail
1✔
219
    extra = 1
1✔
220

221

222
class FachgebietDomainAdminInline(admin.TabularInline):
1✔
223
    model = EmailEndung
1✔
224
    extra = 1
1✔
225

226

227
class FachgebietAdmin(admin.ModelAdmin):
1✔
228
    """Admin View für Fachgebiet"""
229
    list_display = ('name', 'kuerzel')
1✔
230
    list_display_links = ('name',)
1✔
231
    inlines = (FachgebietEmailAdminInline, FachgebietDomainAdminInline,)
1✔
232

233
    def save_related(self, request, form, formsets, change):
1✔
234
        super().save_related(request, form, formsets, change)
1✔
235
        if change:
1✔
236
            count_added = 0
1✔
237
            if EmailEndung.objects.filter(fachgebiet=form.instance).count() != 0:
1✔
238
                persons = Person.objects.filter(fachgebiet=None)
1✔
239
                for person in persons:
1✔
240
                    if not person.email:
1✔
241
                        continue
×
242
                    proposed_fachgebiet = Fachgebiet.get_fachgebiet_from_email(person.email)
1✔
243
                    if proposed_fachgebiet \
1✔
244
                            and proposed_fachgebiet.id == form.instance.id:
245
                        person.fachgebiet = proposed_fachgebiet
1✔
246
                        person.save()
1✔
247
                        count_added += 1
1✔
248
            if count_added > 0:
1✔
249
                self.message_user(request, _("Dieses Fachgebiet wurde {count_added} Personen zugeordnet").format(count_added=count_added))
1✔
250

251

252
class FragebogenAdmin(admin.ModelAdmin):
1✔
253
    """Admin View für Ergebnis2020"""
254
    list_display = ('veranstaltung',)
1✔
255
    list_per_page = 500
1✔
256

257
class EmailChangeAdmin(admin.ModelAdmin):
1✔
258
    fields = (
1✔
259
        "old_email",
260
        "new_email",
261
        "token",
262
        "created_at",
263
        "status",
264
        "person_list_to_change",
265
        "dynamic_expiry_time",
266
    )
267
    list_display = (
1✔
268
        "old_email",
269
        "new_email",
270
        "dynamic_expiry_time",
271
        "created_at",
272
        # "status",  don't put this into here, as get_object (below) or a user action (calling EmailChange.request_is_valid())
273
    )         # has to update status field. This avoids having background workers running to update the fields  
274

275
    readonly_fields = (
1✔
276
        "old_email",
277
        "new_email",
278
        "token",
279
        "dynamic_expiry_time",
280
        "created_at",
281
        "status",
282
        "person_list_to_change",
283
    )
284
    def get_object(self, request, object_id, from_queryset=None):
1✔
285
        """
286
        updates the status, when admin enters into details of an object
287
        """
288
        obj = super().get_object(request, object_id, from_queryset)
×
289

290
        if obj is not None:
×
291
            obj.request_is_valid()
×
292
            
293
        return obj
×
294

295

296
admin.site.register(Person, PersonAdmin)
1✔
297
admin.site.register(Veranstaltung, VeranstaltungAdmin)
1✔
298
admin.site.register(Semester, SemesterAdmin)
1✔
299
admin.site.register(Fragebogen2025, FragebogenAdmin)
1✔
300
admin.site.register(FragebogenUE2025, FragebogenAdmin)
1✔
301
admin.site.register(Ergebnis2025, FragebogenAdmin)
1✔
302
admin.site.register(Fragebogen2020, FragebogenAdmin)
1✔
303
admin.site.register(FragebogenUE2020, FragebogenAdmin)
1✔
304
admin.site.register(Ergebnis2020, FragebogenAdmin)
1✔
305
admin.site.register(Fragebogen2016, FragebogenAdmin)
1✔
306
admin.site.register(FragebogenUE2016, FragebogenAdmin)
1✔
307
admin.site.register(Ergebnis2016, FragebogenAdmin)
1✔
308
admin.site.register(Mailvorlage, MailvorlageAdmin)
1✔
309
admin.site.register(Kommentar, KommentarAdmin)
1✔
310
admin.site.register(Tutor, TutorAdmin)
1✔
311
admin.site.register(BarcodeScannEvent, BarcodeScannEventAdmin)
1✔
312
admin.site.register(BarcodeScanner, BarcodeScannerAdmin)
1✔
313
admin.site.register(Fachgebiet, FachgebietAdmin)
1✔
314
admin.site.register(EmailEndung)
1✔
315
admin.site.register(EmailChange, EmailChangeAdmin)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc