Manuel Gijón
Manuel Gijón

Reputation: 148

File manipulation in Django models.py

I am building a Django app that saves an .stl file passed using a formulary and my goal is to open the file, extract some information with a script that is already tested, and save this information in the same register that the file.

I am doing this:

from stl import mesh # numpy-stl library
def informationGeneration(stl_route, *args, **kwargs):
    # scripts that generates the information 
    myMesh = mesh.Mesh.from_file(stl_route) # here the error appears
    return myMesh.areas.shape[0]

class Piece(models.Model):
    """Piece model."""
    # ...
    file = models.FileField(upload_to='pieces/files', default='NA')
    # ...
    information = models.IntegerField(default=0)

    def save(self, *args, **kwargs):
        """Overriding the save method."""
        self.information = informationGeneration(self.file)
        super().save(*args, **kwargs)
    def __str__(self):
        # ...

The problem is that when I try to save a new instance, numpy-stl detects an error, self.file is not the .stl file, is an alement of the formulary.

Then, I use a form:

class PieceForm(forms.ModelForm):
    """Pieces model form."""
    class Meta:
       """Form settings."""
       model = Piece
       fields = ('file')

How can I pass the file and not the route?

Upvotes: 0

Views: 184

Answers (1)

bruno desthuilliers
bruno desthuilliers

Reputation: 77892

Piece.file is not a path, it's a models.FileField. To get the path, you have to use self.file.path.

Just beware that if there's actually no file for this field, self.file.path will raise an exception (ValueError, "the file attribute has no file associated with it"), so it's better to test before. models.FileField have a false value in a boolean context, so you want:

if self.file:
    self.information = informationGeneration(self.file.path)

A couple notes:

1/ a function is an action, so it's name should be a verb (ie "extract_informations")

2/ you probably don't want to re-parse the file's content each and every time your object is saved, only when the file has changed. You can use a md5sum (stored in the model) to check this.

3/ I have not double-checked but I really dont think you should use a default for this field - if you want to make it optional, use blank=True and null=True.

Upvotes: 1

Related Questions