mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge pull request #703 from SchrodingersGat/fixes
Check for missing part thumbnails
This commit is contained in:
commit
5447bc4356
@ -14,6 +14,41 @@ from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from .version import inventreeVersion, inventreeInstanceName
|
||||
from .settings import MEDIA_URL, STATIC_URL
|
||||
|
||||
|
||||
def getMediaUrl(filename):
|
||||
"""
|
||||
Return the qualified access path for the given file,
|
||||
under the media directory.
|
||||
"""
|
||||
|
||||
return os.path.join(MEDIA_URL, str(filename))
|
||||
|
||||
|
||||
def getStaticUrl(filename):
|
||||
"""
|
||||
Return the qualified access path for the given file,
|
||||
under the static media directory.
|
||||
"""
|
||||
|
||||
return os.path.join(STATIC_URL, str(filename))
|
||||
|
||||
|
||||
def getBlankImage():
|
||||
"""
|
||||
Return the qualified path for the 'blank image' placeholder.
|
||||
"""
|
||||
|
||||
return getStaticUrl("img/blank_image.png")
|
||||
|
||||
|
||||
def getBlankThumbnail():
|
||||
"""
|
||||
Return the qualified path for the 'blank image' thumbnail placeholder.
|
||||
"""
|
||||
|
||||
return getStaticUrl("img/blank_image.thumbnail.png")
|
||||
|
||||
|
||||
def TestIfImage(img):
|
||||
@ -66,7 +101,7 @@ def isNull(text):
|
||||
True if the text looks like a null value
|
||||
"""
|
||||
|
||||
return str(text).strip().lower() in ['top', 'null', 'none', 'empty', 'false', '-1']
|
||||
return str(text).strip().lower() in ['top', 'null', 'none', 'empty', 'false', '-1', '']
|
||||
|
||||
|
||||
def decimal2string(d):
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
from django.test import TestCase
|
||||
import django.core.exceptions as django_exceptions
|
||||
from django.core.exceptions import ValidationError
|
||||
@ -7,6 +8,8 @@ from . import helpers
|
||||
|
||||
from mptt.exceptions import InvalidMove
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from stock.models import StockLocation
|
||||
|
||||
|
||||
@ -72,6 +75,29 @@ class TestHelpers(TestCase):
|
||||
self.assertFalse(helpers.str2bool(s))
|
||||
self.assertFalse(helpers.str2bool(s, test=False))
|
||||
|
||||
def test_isnull(self):
|
||||
|
||||
for s in ['null', 'none', '', '-1', 'false']:
|
||||
self.assertTrue(helpers.isNull(s))
|
||||
|
||||
for s in ['yes', 'frog', 'llama', 'true']:
|
||||
self.assertFalse(helpers.isNull(s))
|
||||
|
||||
def testStaticUrl(self):
|
||||
|
||||
self.assertEqual(helpers.getStaticUrl('test.jpg'), '/static/test.jpg')
|
||||
self.assertEqual(helpers.getBlankImage(), '/static/img/blank_image.png')
|
||||
self.assertEqual(helpers.getBlankThumbnail(), '/static/img/blank_image.thumbnail.png')
|
||||
|
||||
def testMediaUrl(self):
|
||||
|
||||
self.assertEqual(helpers.getMediaUrl('xx/yy.png'), '/media/xx/yy.png')
|
||||
|
||||
def testDecimal2String(self):
|
||||
|
||||
self.assertEqual(helpers.decimal2string(Decimal('1.2345000')), '1.2345')
|
||||
self.assertEqual(helpers.decimal2string('test'), 'test')
|
||||
|
||||
|
||||
class TestQuoteWrap(TestCase):
|
||||
""" Tests for string wrapping """
|
||||
|
@ -1,7 +1,36 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.db.utils import OperationalError, ProgrammingError
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class CompanyConfig(AppConfig):
|
||||
name = 'company'
|
||||
|
||||
def ready(self):
|
||||
"""
|
||||
This function is called whenever the Company app is loaded.
|
||||
"""
|
||||
|
||||
self.generate_company_thumbs()
|
||||
|
||||
def generate_company_thumbs(self):
|
||||
|
||||
from .models import Company
|
||||
|
||||
print("InvenTree: Checking Company image thumbnails")
|
||||
|
||||
try:
|
||||
for company in Company.objects.all():
|
||||
if company.image:
|
||||
url = company.image.thumbnail.name
|
||||
loc = os.path.join(settings.MEDIA_ROOT, url)
|
||||
|
||||
if not os.path.exists(loc):
|
||||
print("InvenTree: Generating thumbnail for Company '{c}'".format(c=company.name))
|
||||
company.image.render_variations(replace=False)
|
||||
except (OperationalError, ProgrammingError):
|
||||
print("Could not generate Company thumbnails")
|
||||
|
20
InvenTree/company/migrations/0014_auto_20200407_0116.py
Normal file
20
InvenTree/company/migrations/0014_auto_20200407_0116.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Generated by Django 2.2.10 on 2020-04-07 01:16
|
||||
|
||||
import company.models
|
||||
from django.db import migrations
|
||||
import stdimage.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('company', '0013_auto_20200406_0131'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='company',
|
||||
name='image',
|
||||
field=stdimage.models.StdImageField(blank=True, null=True, upload_to=company.models.rename_company_image),
|
||||
),
|
||||
]
|
@ -17,10 +17,12 @@ from django.db.models import Sum
|
||||
|
||||
from django.apps import apps
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
|
||||
from markdownx.models import MarkdownxField
|
||||
|
||||
from stdimage.models import StdImageField
|
||||
|
||||
from InvenTree.helpers import getMediaUrl, getBlankImage, getBlankThumbnail
|
||||
from InvenTree.fields import InvenTreeURLField, RoundingDecimalField
|
||||
from InvenTree.status_codes import OrderStatus
|
||||
from common.models import Currency
|
||||
@ -90,7 +92,13 @@ class Company(models.Model):
|
||||
|
||||
link = InvenTreeURLField(blank=True, help_text=_('Link to external company information'))
|
||||
|
||||
image = models.ImageField(upload_to=rename_company_image, max_length=255, null=True, blank=True)
|
||||
image = StdImageField(
|
||||
upload_to=rename_company_image,
|
||||
null=True,
|
||||
blank=True,
|
||||
variations={'thumbnail': (128, 128)},
|
||||
delete_orphans=True,
|
||||
)
|
||||
|
||||
notes = MarkdownxField(blank=True)
|
||||
|
||||
@ -110,10 +118,18 @@ class Company(models.Model):
|
||||
""" Return the URL of the image for this company """
|
||||
|
||||
if self.image:
|
||||
return os.path.join(settings.MEDIA_URL, str(self.image.url))
|
||||
return getMediaUrl(self.image.url)
|
||||
else:
|
||||
return os.path.join(settings.STATIC_URL, 'img/blank_image.png')
|
||||
return getBlankImage()
|
||||
|
||||
def get_thumbnail_url(self):
|
||||
""" Return the URL for the thumbnail image for this Company """
|
||||
|
||||
if self.image:
|
||||
return getMediaUrl(self.image.thumbnail.url)
|
||||
else:
|
||||
return getBlankThumbnail()
|
||||
|
||||
@property
|
||||
def part_count(self):
|
||||
""" The number of parts supplied by this company """
|
||||
|
@ -32,7 +32,7 @@ class CompanySerializer(InvenTreeModelSerializer):
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
part_count = serializers.CharField(read_only=True)
|
||||
|
||||
image = serializers.CharField(source='get_image_url', read_only=True)
|
||||
image = serializers.CharField(source='get_thumbnail_url', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Company
|
||||
@ -64,7 +64,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
|
||||
supplier_name = serializers.CharField(source='supplier.name', read_only=True)
|
||||
supplier_logo = serializers.CharField(source='supplier.get_image_url', read_only=True)
|
||||
supplier_logo = serializers.CharField(source='supplier.get_thumbnail_url', read_only=True)
|
||||
|
||||
pricing = serializers.CharField(source='unit_pricing', read_only=True)
|
||||
|
||||
|
@ -46,7 +46,7 @@ InvenTree | {% trans "Company" %} - {{ company.name }}
|
||||
<col width='25'>
|
||||
{% if company.website %}
|
||||
<tr>
|
||||
<td><span class='fas fa-link'></span></td>
|
||||
<td><span class='fas fa-globe'></span></td>
|
||||
<td>{% trans "Website" %}</td>
|
||||
<td><a href="{{ company.website }}">{{ company.website }}</a></td>
|
||||
</tr>
|
||||
|
@ -1,7 +1,35 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
from django.db.utils import OperationalError, ProgrammingError
|
||||
from django.apps import AppConfig
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class PartConfig(AppConfig):
|
||||
name = 'part'
|
||||
|
||||
def ready(self):
|
||||
"""
|
||||
This function is called whenever the Part app is loaded.
|
||||
"""
|
||||
|
||||
self.generate_part_thumbnails()
|
||||
|
||||
def generate_part_thumbnails(self):
|
||||
from .models import Part
|
||||
|
||||
print("InvenTree: Checking Part image thumbnails")
|
||||
|
||||
try:
|
||||
for part in Part.objects.all():
|
||||
if part.image:
|
||||
url = part.image.thumbnail.name
|
||||
loc = os.path.join(settings.MEDIA_ROOT, url)
|
||||
|
||||
if not os.path.exists(loc):
|
||||
print("InvenTree: Generating thumbnail for Part '{p}'".format(p=part.name))
|
||||
part.image.render_variations(replace=False)
|
||||
except (OperationalError, ProgrammingError):
|
||||
print("Could not generate Part thumbnails")
|
||||
|
@ -10,7 +10,6 @@ import os
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
|
||||
from django.db import models, transaction
|
||||
from django.db.models import Sum
|
||||
@ -300,9 +299,9 @@ class Part(models.Model):
|
||||
""" Return the URL of the image for this part """
|
||||
|
||||
if self.image:
|
||||
return os.path.join(settings.MEDIA_URL, str(self.image.url))
|
||||
return helpers.getMediaUrl(self.image.url)
|
||||
else:
|
||||
return os.path.join(settings.STATIC_URL, 'img/blank_image.png')
|
||||
return helpers.getBlankImage()
|
||||
|
||||
def get_thumbnail_url(self):
|
||||
"""
|
||||
@ -310,9 +309,9 @@ class Part(models.Model):
|
||||
"""
|
||||
|
||||
if self.image:
|
||||
return os.path.join(settings.MEDIA_URL, str(self.image.thumbnail.url))
|
||||
return helpers.getMediaUrl(self.image.thumbnail.url)
|
||||
else:
|
||||
return os.path.join(settings.STATIC_URL, 'img/blank_image.thumbnail.png')
|
||||
return helpers.getBlankThumbnail()
|
||||
|
||||
def validate_unique(self, exclude=None):
|
||||
""" Validate that a part is 'unique'.
|
||||
|
@ -11,7 +11,7 @@
|
||||
{% if item.serialized %}
|
||||
<p><i>{{ item.part.full_name}} # {{ item.serial }}</i></p>
|
||||
{% else %}
|
||||
<p><i>{{ item.quantity }} × {{ item.part.full_name }}</i></p>
|
||||
<p><i>{% decimal item.quantity %} × {{ item.part.full_name }}</i></p>
|
||||
{% endif %}
|
||||
<p>
|
||||
<div class='btn-group'>
|
||||
|
Loading…
Reference in New Issue
Block a user