mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Add image download functionality for company
This commit is contained in:
parent
4e7243b999
commit
9c91ba4692
@ -66,6 +66,24 @@ class CompanyImageForm(HelperForm):
|
||||
]
|
||||
|
||||
|
||||
class CompanyImageDownloadForm(HelperForm):
|
||||
"""
|
||||
Form for downloading an image from a URL
|
||||
"""
|
||||
|
||||
url = django.forms.URLField(
|
||||
label=_('URL'),
|
||||
help_text=_('Image URL'),
|
||||
required=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Company
|
||||
fields = [
|
||||
'url',
|
||||
]
|
||||
|
||||
|
||||
class EditSupplierPartForm(HelperForm):
|
||||
""" Form for editing a SupplierPart object """
|
||||
|
||||
|
@ -2,14 +2,19 @@
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
|
||||
{% block page_title %}
|
||||
InvenTree | {% trans "Company" %} - {{ company.name }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block thumbnail %}
|
||||
{% settings_value "INVENTREE_DOWNLOAD_FROM_URL" as allow_download %}
|
||||
|
||||
<div class='dropzone part-thumb-container' id='company-thumb'>
|
||||
<img class="part-thumb"
|
||||
<img class="part-thumb" id='company-image'
|
||||
{% if company.image %}
|
||||
src="{{ company.image.url }}"
|
||||
{% else %}
|
||||
@ -18,6 +23,9 @@ InvenTree | {% trans "Company" %} - {{ company.name }}
|
||||
<div class='btn-row part-thumb-overlay'>
|
||||
<div class='btn-group'>
|
||||
<button type='button' class='btn btn-default btn-glyph' title='{% trans "Upload new image" %}' id='company-image-upload'><span class='fas fa-file-upload'></span></button>
|
||||
{% if allow_download %}
|
||||
<button type='button' class='btn btn-default btn-glyph' title="{% trans 'Download image from URL' %}" id='company-image-url'><span class='fas fa-cloud-download-alt'></span></button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -141,7 +149,7 @@ InvenTree | {% trans "Company" %} - {{ company.name }}
|
||||
);
|
||||
|
||||
{% if company.image %}
|
||||
$('#company-thumb').click(function() {
|
||||
$('#company-image').click(function() {
|
||||
showModalImage('{{ company.image.url }}');
|
||||
});
|
||||
{% endif %}
|
||||
@ -155,4 +163,17 @@ InvenTree | {% trans "Company" %} - {{ company.name }}
|
||||
);
|
||||
});
|
||||
|
||||
{% settings_value "INVENTREE_DOWNLOAD_FROM_URL" as allow_download %}
|
||||
|
||||
{% if allow_download %}
|
||||
$('#company-image-url').click(function() {
|
||||
launchModalForm(
|
||||
'{% url "company-image-download" company.id %}',
|
||||
{
|
||||
reload: true,
|
||||
}
|
||||
)
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
@ -21,6 +21,7 @@ company_detail_urls = [
|
||||
url(r'^notes/', views.CompanyNotes.as_view(), name='company-notes'),
|
||||
|
||||
url(r'^thumbnail/', views.CompanyImage.as_view(), name='company-image'),
|
||||
url(r'^thumb-download/', views.CompanyImageDownloadFromURL.as_view(), name='company-image-download'),
|
||||
|
||||
# Any other URL
|
||||
url(r'^.*$', views.CompanyDetail.as_view(), name='company-detail'),
|
||||
|
@ -11,9 +11,14 @@ from django.views.generic import DetailView, ListView, UpdateView
|
||||
|
||||
from django.urls import reverse
|
||||
from django.forms import HiddenInput
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
from moneyed import CURRENCIES
|
||||
|
||||
from PIL import Image
|
||||
import requests
|
||||
import io
|
||||
|
||||
from InvenTree.views import AjaxCreateView, AjaxUpdateView, AjaxDeleteView
|
||||
from InvenTree.helpers import str2bool
|
||||
from InvenTree.views import InvenTreeRoleMixin
|
||||
@ -28,6 +33,7 @@ from .forms import EditCompanyForm
|
||||
from .forms import CompanyImageForm
|
||||
from .forms import EditSupplierPartForm
|
||||
from .forms import EditPriceBreakForm
|
||||
from .forms import CompanyImageDownloadForm
|
||||
|
||||
import common.models
|
||||
import common.settings
|
||||
@ -150,6 +156,84 @@ class CompanyDetail(DetailView):
|
||||
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', f"{_('Invalid response')}: {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 CompanyImage(AjaxUpdateView):
|
||||
""" View for uploading an image for the Company """
|
||||
model = Company
|
||||
|
@ -7,7 +7,7 @@
|
||||
<div class="media">
|
||||
<div class="media-left part-thumb-container">
|
||||
<div class='dropzone' id='part-thumb'>
|
||||
<img class="part-thumb"
|
||||
<img class="part-thumb" id='part-image'
|
||||
{% if part.image %}
|
||||
src="{{ part.image.url }}"
|
||||
{% else %}
|
||||
|
@ -843,7 +843,7 @@ class PartImageDownloadFromURL(AjaxUpdateView):
|
||||
|
||||
model = Part
|
||||
|
||||
ajax_template_name = 'part/image_download.html'
|
||||
ajax_template_name = 'image_download.html'
|
||||
form_class = part_forms.PartImageDownloadForm
|
||||
ajax_form_title = _('Download Image')
|
||||
|
||||
@ -890,7 +890,7 @@ class PartImageDownloadFromURL(AjaxUpdateView):
|
||||
response.raw.decode_content = True
|
||||
|
||||
try:
|
||||
self.image = Image.open(response.raw).convert('RGB')
|
||||
self.image = Image.open(response.raw).convert()
|
||||
self.image.verify()
|
||||
except:
|
||||
form.add_error('url', _("Supplied URL is not a valid image file"))
|
||||
|
Loading…
Reference in New Issue
Block a user