permit PDF as well as images for invoice uploads for expenses
This commit is contained in:
parent
ed736938cc
commit
93b0bff50b
38
src/economy/forms.py
Normal file
38
src/economy/forms.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import os, magic, copy
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from .models import Expense
|
||||||
|
|
||||||
|
|
||||||
|
class ExpenseCreateForm(forms.ModelForm):
|
||||||
|
"""
|
||||||
|
We have to define this form explicitly because we want our ImageField to accept PDF files as well as images,
|
||||||
|
and we cannot change the clean_* methods with an autogenerated form from inside views.py
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
model = Expense
|
||||||
|
fields = ['description', 'amount', 'invoice', 'paid_by_bornhack', 'responsible_team']
|
||||||
|
|
||||||
|
invoice = forms.FileField()
|
||||||
|
|
||||||
|
def clean_invoice(self):
|
||||||
|
# get the uploaded file from cleaned_data
|
||||||
|
uploaded_file = self.cleaned_data['invoice']
|
||||||
|
# is this a valid image?
|
||||||
|
try:
|
||||||
|
# create an ImageField instance
|
||||||
|
im = forms.ImageField()
|
||||||
|
# now check if the file is a valid image
|
||||||
|
im.to_python(uploaded_file)
|
||||||
|
except forms.ValidationError:
|
||||||
|
# file is not a valid image, so check if it's a pdf
|
||||||
|
# do a deep copy so we dont mess with the file object we might be passing on
|
||||||
|
testfile = copy.deepcopy(uploaded_file)
|
||||||
|
# read the uploaded file into memory (the webserver limits uploads to a reasonable max size so this should be safe)
|
||||||
|
mimetype = magic.from_buffer(testfile.open().read(), mime=True)
|
||||||
|
if mimetype != "application/pdf":
|
||||||
|
raise forms.ValidationError("Only images and PDF files allowed")
|
||||||
|
|
||||||
|
# this is either a valid image, or has mimetype application/pdf, all good
|
||||||
|
return uploaded_file
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>Invoice</th>
|
<th>Invoice</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'economy:expense_invoice' camp_slug=camp.slug pk=expense.pk %}"><img src="{% url 'economy:expense_invoice' camp_slug=camp.slug pk=expense.pk %}" height=200></a><br>
|
<a href="{% url 'economy:expense_invoice' camp_slug=camp.slug pk=expense.pk %}"><img src="{% url 'economy:expense_invoice' camp_slug=camp.slug pk=expense.pk %}?preview" height=200></a><br>
|
||||||
Filename: {{ expense.invoice_filename }}
|
Filename: {{ expense.invoice_filename }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import magic
|
import os, magic
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -15,6 +15,7 @@ from utils.mixins import RaisePermissionRequiredMixin
|
||||||
from teams.models import Team
|
from teams.models import Team
|
||||||
from .models import Expense, Reimbursement
|
from .models import Expense, Reimbursement
|
||||||
from .mixins import ExpensePermissionMixin, ReimbursementPermissionMixin
|
from .mixins import ExpensePermissionMixin, ReimbursementPermissionMixin
|
||||||
|
from .forms import ExpenseCreateForm
|
||||||
|
|
||||||
|
|
||||||
class ExpenseListView(LoginRequiredMixin, CampViewMixin, ListView):
|
class ExpenseListView(LoginRequiredMixin, CampViewMixin, ListView):
|
||||||
|
@ -41,9 +42,9 @@ class ExpenseDetailView(CampViewMixin, ExpensePermissionMixin, DetailView):
|
||||||
|
|
||||||
class ExpenseCreateView(CampViewMixin, RaisePermissionRequiredMixin, CreateView):
|
class ExpenseCreateView(CampViewMixin, RaisePermissionRequiredMixin, CreateView):
|
||||||
model = Expense
|
model = Expense
|
||||||
fields = ['description', 'amount', 'invoice', 'paid_by_bornhack', 'responsible_team']
|
|
||||||
template_name = 'expense_form.html'
|
template_name = 'expense_form.html'
|
||||||
permission_required = ("camps.expense_create_permission")
|
permission_required = ("camps.expense_create_permission")
|
||||||
|
form_class = ExpenseCreateForm
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -92,6 +93,10 @@ class ExpenseInvoiceView(CampViewMixin, ExpensePermissionMixin, DetailView):
|
||||||
invoicedata = expense.invoice.read()
|
invoicedata = expense.invoice.read()
|
||||||
# find mimetype
|
# find mimetype
|
||||||
mimetype = magic.from_buffer(invoicedata, mime=True)
|
mimetype = magic.from_buffer(invoicedata, mime=True)
|
||||||
|
# check if we have a PDF, no preview if so, load a pdf icon instead
|
||||||
|
if mimetype=="application/pdf" and 'preview' in request.GET:
|
||||||
|
invoicedata = open(os.path.join(settings.DJANGO_BASE_PATH, "static_src/img/pdf.png"), "rb").read()
|
||||||
|
mimetype = magic.from_buffer(invoicedata, mime=True)
|
||||||
# put the response together and return it
|
# put the response together and return it
|
||||||
response = HttpResponse(content_type=mimetype)
|
response = HttpResponse(content_type=mimetype)
|
||||||
response.write(invoicedata)
|
response.write(invoicedata)
|
||||||
|
|
BIN
src/static_src/img/pdf.png
Normal file
BIN
src/static_src/img/pdf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Loading…
Reference in a new issue