mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Move "rebuild_thumbnails" to being a management command
- Does not run every time the server reboots - Has to be called manually - Normally does not need to be run and is a long-running process!
This commit is contained in:
parent
17df4ca91e
commit
0c04bfaa85
@ -0,0 +1,70 @@
|
|||||||
|
"""
|
||||||
|
Custom management command to rebuild thumbnail images
|
||||||
|
|
||||||
|
- May be required after importing a new dataset, for example
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from PIL import UnidentifiedImageError
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db.utils import OperationalError, ProgrammingError
|
||||||
|
|
||||||
|
from company.models import Company
|
||||||
|
from part.models import Part
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger("inventree-thumbnails")
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""
|
||||||
|
Rebuild all thumbnail images
|
||||||
|
"""
|
||||||
|
|
||||||
|
def rebuild_thumbnail(self, model):
|
||||||
|
"""
|
||||||
|
Rebuild the thumbnail specified by the "image" field of the provided model
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not model.image:
|
||||||
|
return
|
||||||
|
|
||||||
|
img = model.image
|
||||||
|
url = img.thumbnail.name
|
||||||
|
loc = os.path.join(settings.MEDIA_ROOT, url)
|
||||||
|
|
||||||
|
if not os.path.exists(loc):
|
||||||
|
logger.info(f"Generating thumbnail image for '{img}'")
|
||||||
|
|
||||||
|
try:
|
||||||
|
model.image.render_variations(replace=False)
|
||||||
|
except FileNotFoundError:
|
||||||
|
logger.error(f"ERROR: Image file '{img}' is missing")
|
||||||
|
except UnidentifiedImageError:
|
||||||
|
logger.error(f"ERROR: Image file '{img}' is not a valid image")
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
logger.info("Rebuilding Part thumbnails")
|
||||||
|
|
||||||
|
for part in Part.objects.exclude(image=None):
|
||||||
|
try:
|
||||||
|
self.rebuild_thumbnail(part)
|
||||||
|
except (OperationalError, ProgrammingError):
|
||||||
|
logger.error("ERROR: Database read error.")
|
||||||
|
break
|
||||||
|
|
||||||
|
logger.info("Rebuilding Company thumbnails")
|
||||||
|
|
||||||
|
for company in Company.objects.exclude(image=None):
|
||||||
|
try:
|
||||||
|
self.rebuild_thumbnail(company)
|
||||||
|
except (OperationalError, ProgrammingError):
|
||||||
|
logger.error("ERROR: abase read error.")
|
||||||
|
break
|
@ -23,29 +23,4 @@ class CompanyConfig(AppConfig):
|
|||||||
This function is called whenever the Company app is loaded.
|
This function is called whenever the Company app is loaded.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if canAppAccessDatabase():
|
pass
|
||||||
self.generate_company_thumbs()
|
|
||||||
|
|
||||||
def generate_company_thumbs(self):
|
|
||||||
|
|
||||||
from .models import Company
|
|
||||||
|
|
||||||
logger.debug("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):
|
|
||||||
logger.info("InvenTree: Generating thumbnail for Company '{c}'".format(c=company.name))
|
|
||||||
try:
|
|
||||||
company.image.render_variations(replace=False)
|
|
||||||
except FileNotFoundError:
|
|
||||||
logger.warning(f"Image file '{company.image}' missing")
|
|
||||||
except UnidentifiedImageError:
|
|
||||||
logger.warning(f"Image file '{company.image}' is invalid")
|
|
||||||
except (OperationalError, ProgrammingError):
|
|
||||||
# Getting here probably meant the database was in test mode
|
|
||||||
pass
|
|
||||||
|
@ -24,40 +24,8 @@ class PartConfig(AppConfig):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if canAppAccessDatabase():
|
if canAppAccessDatabase():
|
||||||
self.generate_part_thumbnails()
|
|
||||||
self.update_trackable_status()
|
self.update_trackable_status()
|
||||||
|
|
||||||
def generate_part_thumbnails(self):
|
|
||||||
"""
|
|
||||||
Generate thumbnail images for any Part that does not have one.
|
|
||||||
This function exists mainly for legacy support,
|
|
||||||
as any *new* image uploaded will have a thumbnail generated automatically.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .models import Part
|
|
||||||
|
|
||||||
logger.debug("InvenTree: Checking Part image thumbnails")
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Only check parts which have images
|
|
||||||
for part in Part.objects.exclude(image=None):
|
|
||||||
if part.image:
|
|
||||||
url = part.image.thumbnail.name
|
|
||||||
loc = os.path.join(settings.MEDIA_ROOT, url)
|
|
||||||
|
|
||||||
if not os.path.exists(loc):
|
|
||||||
logger.info("InvenTree: Generating thumbnail for Part '{p}'".format(p=part.name))
|
|
||||||
try:
|
|
||||||
part.image.render_variations(replace=False)
|
|
||||||
except FileNotFoundError:
|
|
||||||
logger.warning(f"Image file '{part.image}' missing")
|
|
||||||
pass
|
|
||||||
except UnidentifiedImageError:
|
|
||||||
logger.warning(f"Image file '{part.image}' is invalid")
|
|
||||||
except (OperationalError, ProgrammingError):
|
|
||||||
# Exception if the database has not been migrated yet
|
|
||||||
pass
|
|
||||||
|
|
||||||
def update_trackable_status(self):
|
def update_trackable_status(self):
|
||||||
"""
|
"""
|
||||||
Check for any instances where a trackable part is used in the BOM
|
Check for any instances where a trackable part is used in the BOM
|
||||||
|
17
tasks.py
17
tasks.py
@ -127,13 +127,20 @@ def worker(c):
|
|||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def rebuild(c):
|
def rebuild_models(c):
|
||||||
"""
|
"""
|
||||||
Rebuild database models with MPTT structures
|
Rebuild database models with MPTT structures
|
||||||
"""
|
"""
|
||||||
|
|
||||||
manage(c, "rebuild_models")
|
manage(c, "rebuild_models", pty=True)
|
||||||
|
|
||||||
|
@task
|
||||||
|
def rebuild_thumbnails(c):
|
||||||
|
"""
|
||||||
|
Rebuild missing image thumbnails
|
||||||
|
"""
|
||||||
|
|
||||||
|
manage(c, "rebuild_thumbnails", pty=True)
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def clean_settings(c):
|
def clean_settings(c):
|
||||||
@ -143,7 +150,7 @@ def clean_settings(c):
|
|||||||
|
|
||||||
manage(c, "clean_settings")
|
manage(c, "clean_settings")
|
||||||
|
|
||||||
@task(post=[rebuild])
|
@task(post=[rebuild_models, rebuild_thumbnails])
|
||||||
def migrate(c):
|
def migrate(c):
|
||||||
"""
|
"""
|
||||||
Performs database migrations.
|
Performs database migrations.
|
||||||
@ -341,7 +348,7 @@ def export_records(c, filename='data.json'):
|
|||||||
print("Data export completed")
|
print("Data export completed")
|
||||||
|
|
||||||
|
|
||||||
@task(help={'filename': 'Input filename'}, post=[rebuild])
|
@task(help={'filename': 'Input filename'}, post=[rebuild_models, rebuild_thumbnails])
|
||||||
def import_records(c, filename='data.json'):
|
def import_records(c, filename='data.json'):
|
||||||
"""
|
"""
|
||||||
Import database records from a file
|
Import database records from a file
|
||||||
@ -399,7 +406,7 @@ def delete_data(c, force=False):
|
|||||||
manage(c, 'flush')
|
manage(c, 'flush')
|
||||||
|
|
||||||
|
|
||||||
@task(post=[rebuild])
|
@task(post=[rebuild_models, rebuild_thumbnails])
|
||||||
def import_fixtures(c):
|
def import_fixtures(c):
|
||||||
"""
|
"""
|
||||||
Import fixture data into the database.
|
Import fixture data into the database.
|
||||||
|
Loading…
Reference in New Issue
Block a user