From e9b80e2e917235b7461cf497e429fc7d772f6741 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Wed, 20 Jun 2018 20:57:53 +0200 Subject: [PATCH] Allow accessing documents from admin pages Closes #642 --- website/documents/admin.py | 13 ++-- website/documents/forms.py | 69 +++++++++++++++++-- .../widgets/clearable_file_input.html | 5 ++ website/documents/views.py | 10 ++- 4 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 website/documents/templates/widgets/clearable_file_input.html diff --git a/website/documents/admin.py b/website/documents/admin.py index b267df39..2b369dba 100644 --- a/website/documents/admin.py +++ b/website/documents/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.utils.translation import ugettext_lazy as _ -from documents.forms import AnnualDocumentForm, GeneralMeetingForm +from documents import forms from documents.models import (AnnualDocument, AssociationDocument, GeneralMeeting, Minutes, MiscellaneousDocument) @@ -12,13 +12,13 @@ from utils.translation import TranslatedModelAdmin class MinutesInline(admin.StackedInline): """Inline for minutes of a general meeting""" model = Minutes - fields = ('file_nl', 'file_en', 'members_only',) + form = forms.MinutesForm @admin.register(GeneralMeeting) class GeneralMeetingAdmin(TranslatedModelAdmin): """Manage the general meetings""" - form = GeneralMeetingForm + form = forms.GeneralMeetingForm inlines = [ MinutesInline, ] @@ -51,20 +51,19 @@ class LectureYearFilter(admin.SimpleListFilter): @admin.register(AnnualDocument) class AnnualDocumentAdmin(TranslatedModelAdmin): """Manage the annual documents""" - form = AnnualDocumentForm - fields = ('file', 'subcategory', 'year', 'members_only',) + form = forms.AnnualDocumentForm list_filter = (LectureYearFilter, 'created', 'last_updated',) @admin.register(AssociationDocument) class AssociationDocumentAdmin(TranslatedModelAdmin): """Manage the association documents""" - fields = ('name', 'file', 'members_only',) + form = forms.AssociationDocumentForm list_filter = ('created', 'last_updated',) @admin.register(MiscellaneousDocument) class MiscellaneousDocumentAdmin(TranslatedModelAdmin): """Manage the miscellaneous documents""" - fields = ('name', 'file', 'members_only',) + form = forms.MiscellaneousDocumentForm list_filter = ('created', 'last_updated',) diff --git a/website/documents/forms.py b/website/documents/forms.py index fb87c9ec..8c79ab9d 100644 --- a/website/documents/forms.py +++ b/website/documents/forms.py @@ -1,24 +1,63 @@ """The forms defined by the documents package""" from django import forms from django.contrib import admin +from django.db.models import Q +from django.forms import widgets from django.utils import timezone -from documents.models import AnnualDocument, GeneralMeeting +from documents import models from utils.snippets import datetime_to_lectureyear +class DocumentFileInput(widgets.ClearableFileInput): + """ + Wrapper around Django's :class:`~django.forms.widgets.ClearableFileInput` + + It overrides the URL of the associated file when it is fetched. + """ + template_name = 'widgets/clearable_file_input.html' + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + if hasattr(value, 'url'): + doc = models.Document.objects.get(Q(file_en=value) | + Q(file_nl=value)) + context['document_id'] = doc.pk + if doc.file_en == value: + context['language'] = 'en' + else: + context['language'] = 'nl' + return context + + +class MinutesForm(forms.ModelForm): + """Form that overrides the widgets for the files""" + class Meta: + model = models.Minutes + fields = ('file_nl', 'file_en', 'members_only',) + widgets = { + 'file_nl': DocumentFileInput, + 'file_en': DocumentFileInput, + } + + class AnnualDocumentForm(forms.ModelForm): + """Form that provides custom functionality for annual documents""" class Meta: - model = AnnualDocument + model = models.AnnualDocument exclude = () widgets = { - 'year': forms.Select + 'year': forms.Select, + 'file_nl': DocumentFileInput, + 'file_en': DocumentFileInput, } def current_year(): + """Get the current lecture year""" return datetime_to_lectureyear(timezone.now()) def year_choices(): + """Get the lecture years""" current = datetime_to_lectureyear(timezone.now()) return [ (year, "{}-{}".format(year, year+1)) @@ -29,10 +68,32 @@ class AnnualDocumentForm(forms.ModelForm): initial=current_year) +class AssociationDocumentForm(forms.ModelForm): + """Form that overrides the widgets for the files""" + class Meta: + model = models.AssociationDocument + fields = ('name_en', 'name_nl', 'file_en', 'file_nl', 'members_only',) + widgets = { + 'file_nl': DocumentFileInput, + 'file_en': DocumentFileInput, + } + + +class MiscellaneousDocumentForm(forms.ModelForm): + """Form that overrides the widgets for the files""" + class Meta: + model = models.MiscellaneousDocument + fields = ('name_en', 'name_nl', 'file_en', 'file_nl', 'members_only',) + widgets = { + 'file_nl': DocumentFileInput, + 'file_en': DocumentFileInput, + } + + class GeneralMeetingForm(forms.ModelForm): """Custom form for general meetings with a custom widget for documents""" class Meta: - model = GeneralMeeting + model = models.GeneralMeeting exclude = () widgets = { 'documents': admin.widgets.FilteredSelectMultiple( diff --git a/website/documents/templates/widgets/clearable_file_input.html b/website/documents/templates/widgets/clearable_file_input.html new file mode 100644 index 00000000..c0d700e8 --- /dev/null +++ b/website/documents/templates/widgets/clearable_file_input.html @@ -0,0 +1,5 @@ +{% if widget.is_initial %}{{ widget.initial_text }}: {{ widget.value }}{% if not widget.required %} + +{% endif %}
+{{ widget.input_text }}:{% endif %} + diff --git a/website/documents/views.py b/website/documents/views.py index be9f5812..d266c87b 100644 --- a/website/documents/views.py +++ b/website/documents/views.py @@ -64,12 +64,18 @@ def get_document(request, pk): if document.members_only and not request.user.is_authenticated: return redirect('{}?next={}'.format(settings.LOGIN_URL, request.path)) + lang = request.GET.get('language') try: - file = document.file + if lang == 'nl': + file = document.file_nl + elif lang == 'en': + file = document.file_en + else: # Fall back on language detection + file = document.file except ValueError: raise Http404('This document does not exist.') ext = os.path.splitext(file.path)[1] - return sendfile(request, document.file.path, attachment=True, + return sendfile(request, file.path, attachment=True, attachment_filename=slugify(document.name) + ext) -- GitLab