InvenTree/InvenTree/company/views.py

225 lines
6.1 KiB
Python

"""
Django views for interacting with Company app
"""
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.views.generic import DetailView, ListView
from django.urls import reverse
from django.core.files.base import ContentFile
from PIL import Image
import requests
import io
from InvenTree.views import AjaxUpdateView
from InvenTree.views import InvenTreeRoleMixin
from .models import Company
from .models import ManufacturerPart
from .models import SupplierPart
from .forms import CompanyImageDownloadForm
class CompanyIndex(InvenTreeRoleMixin, ListView):
""" View for displaying list of companies
"""
model = Company
template_name = 'company/index.html'
context_object_name = 'companies'
paginate_by = 50
permission_required = 'company.view_company'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
# Provide custom context data to the template,
# based on the URL we use to access this page
lookup = {
reverse('supplier-index'): {
'title': _('Suppliers'),
'button_text': _('New Supplier'),
'filters': {'is_supplier': 'true'},
'pagetype': 'suppliers',
},
reverse('manufacturer-index'): {
'title': _('Manufacturers'),
'button_text': _('New Manufacturer'),
'filters': {'is_manufacturer': 'true'},
'pagetype': 'manufacturers',
},
reverse('customer-index'): {
'title': _('Customers'),
'button_text': _('New Customer'),
'filters': {'is_customer': 'true'},
'pagetype': 'customers',
}
}
default = {
'title': _('Companies'),
'button_text': _('New Company'),
'filters': {},
'pagetype': 'companies'
}
context = None
for item in lookup:
if self.request.path == item:
context = lookup[item]
break
if context is None:
context = default
for key, value in context.items():
ctx[key] = value
return ctx
def get_queryset(self):
""" Retrieve the Company queryset based on HTTP request parameters.
- supplier: Filter by supplier
- customer: Filter by customer
"""
queryset = Company.objects.all().order_by('name')
if self.request.GET.get('supplier', None):
queryset = queryset.filter(is_supplier=True)
if self.request.GET.get('customer', None):
queryset = queryset.filter(is_customer=True)
return queryset
class CompanyDetail(DetailView):
""" Detail view for Company object """
context_obect_name = 'company'
template_name = 'company/detail.html'
queryset = Company.objects.all()
model = Company
permission_required = 'company.view_company'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
return ctx
class CompanyImageDownloadFromURL(AjaxUpdateView):
"""
View for downloading an image from a provided URL
"""
model = Company
ajax_template_name = 'image_download.html'
form_class = CompanyImageDownloadForm
ajax_form_title = _('Download Image')
def validate(self, company, form):
"""
Validate that the image data are correct
"""
# First ensure that the normal validation routines pass
if not form.is_valid():
return
# We can now extract a valid URL from the form data
url = form.cleaned_data.get('url', None)
# Download the file
response = requests.get(url, stream=True)
# Look at response header, reject if too large
content_length = response.headers.get('Content-Length', '0')
try:
content_length = int(content_length)
except (ValueError):
# If we cannot extract meaningful length, just assume it's "small enough"
content_length = 0
# TODO: Factor this out into a configurable setting
MAX_IMG_LENGTH = 10 * 1024 * 1024
if content_length > MAX_IMG_LENGTH:
form.add_error('url', _('Image size exceeds maximum allowable size for download'))
return
self.response = response
# Check for valid response code
if not response.status_code == 200:
form.add_error('url', _('Invalid response: {code}').format(code=response.status_code))
return
response.raw.decode_content = True
try:
self.image = Image.open(response.raw).convert()
self.image.verify()
except:
form.add_error('url', _("Supplied URL is not a valid image file"))
return
def save(self, company, form, **kwargs):
"""
Save the downloaded image to the company
"""
fmt = self.image.format
if not fmt:
fmt = 'PNG'
buffer = io.BytesIO()
self.image.save(buffer, format=fmt)
# Construct a simplified name for the image
filename = f"company_{company.pk}_image.{fmt.lower()}"
company.image.save(
filename,
ContentFile(buffer.getvalue()),
)
class ManufacturerPartDetail(DetailView):
""" Detail view for ManufacturerPart """
model = ManufacturerPart
template_name = 'company/manufacturer_part_detail.html'
context_object_name = 'part'
queryset = ManufacturerPart.objects.all()
permission_required = 'purchase_order.view'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
return ctx
class SupplierPartDetail(DetailView):
""" Detail view for SupplierPart """
model = SupplierPart
template_name = 'company/supplier_part_detail.html'
context_object_name = 'part'
queryset = SupplierPart.objects.all()
permission_required = 'purchase_order.view'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
return ctx