Commit 2092340a authored by Sébastiaan Versteeg's avatar Sébastiaan Versteeg
Browse files

Merge branch 'fix-admin-documents' into 'master'

Allow accessing documents from admin pages

Closes #642

See merge request !841
parents 7b259d67 e9b80e2e
......@@ -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,
......@@ -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
class GeneralMeetingAdmin(TranslatedModelAdmin):
"""Manage the general meetings"""
form = GeneralMeetingForm
form = forms.GeneralMeetingForm
inlines = [
......@@ -51,20 +51,19 @@ class LectureYearFilter(admin.SimpleListFilter):
class AnnualDocumentAdmin(TranslatedModelAdmin):
"""Manage the annual documents"""
form = AnnualDocumentForm
fields = ('file', 'subcategory', 'year', 'members_only',)
form = forms.AnnualDocumentForm
list_filter = (LectureYearFilter, 'created', 'last_updated',)
class AssociationDocumentAdmin(TranslatedModelAdmin):
"""Manage the association documents"""
fields = ('name', 'file', 'members_only',)
form = forms.AssociationDocumentForm
list_filter = ('created', 'last_updated',)
class MiscellaneousDocumentAdmin(TranslatedModelAdmin):
"""Manage the miscellaneous documents"""
fields = ('name', 'file', 'members_only',)
form = forms.MiscellaneousDocumentForm
list_filter = ('created', 'last_updated',)
"""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) |
context['document_id'] =
if doc.file_en == value:
context['language'] = 'en'
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(
def year_choices():
"""Get the lecture years"""
current = datetime_to_lectureyear(
return [
(year, "{}-{}".format(year, year+1))
......@@ -29,10 +68,32 @@ class AnnualDocumentForm(forms.ModelForm):
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(
{% if widget.is_initial %}{{ widget.initial_text }}: <a href="{% url 'documents:document' pk=document_id %}?language={{ language }}">{{ widget.value }}</a>{% if not widget.required %}
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}">
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}<br>
{{ widget.input_text }}:{% endif %}
<input type="{{ widget.type }}" name="{{ }}"{% include "django/forms/widgets/attrs.html" %}>
......@@ -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')
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( + ext)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment