103 lines
2.7 KiB
Python
103 lines
2.7 KiB
Python
"""Various helper functions for the part app."""
|
|
|
|
import logging
|
|
import os
|
|
|
|
from django.conf import settings
|
|
|
|
from jinja2 import Environment, select_autoescape
|
|
|
|
logger = logging.getLogger('inventree')
|
|
|
|
|
|
# Compiled template for rendering the 'full_name' attribute of a Part
|
|
_part_full_name_template = None
|
|
_part_full_name_template_string = ''
|
|
|
|
|
|
def compile_full_name_template(*args, **kwargs):
|
|
"""Recompile the template for rendering the 'full_name' attribute of a Part.
|
|
|
|
This function is called whenever the 'PART_NAME_FORMAT' setting is changed.
|
|
"""
|
|
from common.models import InvenTreeSetting
|
|
|
|
global _part_full_name_template
|
|
global _part_full_name_template_string
|
|
|
|
template_string = InvenTreeSetting.get_setting(
|
|
'PART_NAME_FORMAT', backup_value='', cache=True
|
|
)
|
|
|
|
# Skip if the template string has not changed
|
|
if (
|
|
template_string == _part_full_name_template_string
|
|
and _part_full_name_template is not None
|
|
):
|
|
return _part_full_name_template
|
|
|
|
# Cache the template string
|
|
_part_full_name_template_string = template_string
|
|
|
|
env = Environment(
|
|
autoescape=select_autoescape(default_for_string=False, default=False),
|
|
variable_start_string='{{',
|
|
variable_end_string='}}',
|
|
)
|
|
|
|
# Compile the template
|
|
try:
|
|
_part_full_name_template = env.from_string(template_string)
|
|
except Exception:
|
|
_part_full_name_template = None
|
|
|
|
return _part_full_name_template
|
|
|
|
|
|
def render_part_full_name(part) -> str:
|
|
"""Render the 'full_name' attribute of a Part.
|
|
|
|
To improve render efficiency, we re-compile the template whenever the setting is changed
|
|
|
|
Args:
|
|
part: The Part object to render
|
|
"""
|
|
template = compile_full_name_template()
|
|
|
|
if template:
|
|
try:
|
|
return template.render(part=part)
|
|
except Exception as e:
|
|
logger.warning(
|
|
'exception while trying to create full name for part %s: %s',
|
|
part.name,
|
|
e,
|
|
)
|
|
|
|
# Fallback to the default format
|
|
elements = [el for el in [part.IPN, part.name, part.revision] if el]
|
|
return ' | '.join(elements)
|
|
|
|
|
|
# Subdirectory for storing part images
|
|
PART_IMAGE_DIR = 'part_images'
|
|
|
|
|
|
def get_part_image_directory() -> str:
|
|
"""Return the directory where part images are stored.
|
|
|
|
Returns:
|
|
str: Directory where part images are stored
|
|
|
|
TODO: Future work may be needed here to support other storage backends, such as S3
|
|
"""
|
|
part_image_directory = os.path.abspath(
|
|
os.path.join(settings.MEDIA_ROOT, PART_IMAGE_DIR)
|
|
)
|
|
|
|
# Create the directory if it does not exist
|
|
if not os.path.exists(part_image_directory):
|
|
os.makedirs(part_image_directory)
|
|
|
|
return part_image_directory
|