From a661d7e1a62520a7fb4adb59e4b761c1ad2a2b04 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 22 Mar 2020 17:59:23 +1100 Subject: [PATCH] Abstract the PartAttachment class Now "Attachments" are much easier to implement for different models --- InvenTree/InvenTree/models.py | 48 +++++++++++++++++++ .../migrations/0032_auto_20200322_0453.py | 19 ++++++++ InvenTree/part/models.py | 24 ++-------- 3 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 InvenTree/part/migrations/0032_auto_20200322_0453.py diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py index a60935b4b6..d2a5c5daa6 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -4,8 +4,11 @@ Generic models which provide extra functionality over base Django model types. from __future__ import unicode_literals +import os + from django.db import models from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext_lazy as _ from django.db.models.signals import pre_delete from django.dispatch import receiver @@ -15,6 +18,51 @@ from mptt.models import MPTTModel, TreeForeignKey from .validators import validate_tree_name +def rename_attachment(instance, filename): + """ + Function for renaming an attachment file. + The subdirectory for the uploaded file is determined by the implementing class. + + Args: + instance: Instance of a PartAttachment object + filename: name of uploaded file + + Returns: + path to store file, format: '//filename' + """ + + # Construct a path to store a file attachment for a given model type + return os.path.join(instance.getSubdir(), filename) + + +class InvenTreeAttachment(models.Model): + """ Provides an abstracted class for managing file attachments. + + Attributes: + attachment: File + comment: String descriptor for the attachment + """ + def getSubdir(self): + """ + Return the subdirectory under which attachments should be stored. + Note: Re-implement this for each subclass of InvenTreeAttachment + """ + + return "attachments" + + attachment = models.FileField(upload_to=rename_attachment, + help_text=_('Select file to attach')) + + comment = models.CharField(max_length=100, help_text=_('File comment')) + + @property + def basename(self): + return os.path.basename(self.attachment.name) + + class Meta: + abstract = True + + class InvenTreeTree(MPTTModel): """ Provides an abstracted self-referencing tree model for data categories. diff --git a/InvenTree/part/migrations/0032_auto_20200322_0453.py b/InvenTree/part/migrations/0032_auto_20200322_0453.py new file mode 100644 index 0000000000..29fb25f1e7 --- /dev/null +++ b/InvenTree/part/migrations/0032_auto_20200322_0453.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.9 on 2020-03-22 04:53 + +import InvenTree.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0031_auto_20200318_1044'), + ] + + operations = [ + migrations.AlterField( + model_name='partattachment', + name='attachment', + field=models.FileField(help_text='Select file to attach', upload_to=InvenTree.models.rename_attachment), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index d8cb8b07e0..427cf4dcea 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -34,7 +34,7 @@ import hashlib from InvenTree import helpers from InvenTree import validators -from InvenTree.models import InvenTreeTree +from InvenTree.models import InvenTreeTree, InvenTreeAttachment from InvenTree.fields import InvenTreeURLField from InvenTree.helpers import decimal2string @@ -941,28 +941,14 @@ def attach_file(instance, filename): return os.path.join('part_files', str(instance.part.id), filename) -class PartAttachment(models.Model): - """ A PartAttachment links a file to a part - Parts can have multiple files such as datasheets, etc - - Attributes: - part: Link to a Part object - attachment: File - comment: String descriptor for the attachment - """ +class PartAttachment(InvenTreeAttachment): + + def getSubdir(self): + return os.path.join("part_files", str(self.part.id)) part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='attachments') - attachment = models.FileField(upload_to=attach_file, - help_text=_('Select file to attach')) - - comment = models.CharField(max_length=100, help_text=_('File comment')) - - @property - def basename(self): - return os.path.basename(self.attachment.name) - class PartStar(models.Model): """ A PartStar object creates a relationship between a User and a Part.