0

Intro: I have a small piece of code that takes any image that is being added and makes it smaller and saves it. I am using a external library called Filepond for this.

The Issue: If 2 users add same names to their images(different images). The second users image replaces the 1st users image and both users see the same image.

What I want: Add unique image names. My tries are below the present code. I need the best solution for this so the names are not too big but are unique

Present Code:

fields.py:

class FilePondField(forms.FileField):
widget = forms.TextInput(attrs={'class': 'fileid'})

def __init__(self, name, *args, **kwargs):
    super(FilePondField, self).__init__(*args, **kwargs)
    self.name = name

def prepare_value(self, data):
    if not data:
        return None

    if isinstance(data, str):
        try:
            tu = TU.objects.get(upload_id=data)
        except TU.DoesNotExist:
            return None
        return tu.upload_id

    name = data.name
    base = os.path.basename(name)
    file_id = "%s_%s" % (self.name, data.instance.pk)
    try:
        tu = TU.objects.get(file_id=file_id)
    except TU.DoesNotExist:
        upload_id = uuid()
        tu = TU(upload_id=upload_id, file_id=file_id,  # uuid(),
                upload_name=base, upload_type=TU.FILE_DATA)
        try:
            with data.storage.open(name, 'rb') as f:
                rd_data = File(f)
                tu.file.save(tu.file_id, rd_data, True)
            tu.save()
        except:
            pass

    return tu.upload_id

def clean(self, data, initial=None):
    self.initial = initial
    if not data:
        if self.required:
            raise ValidationError(self.error_messages['required'], code='required')
        return None
    return data

def save_cb(self, instance, modfld, tu):
    prename = os.path.join(modfld.upload_to, tu.upload_name)
    ffile = ImageFieldFile(instance, modfld, prename)

    try:
        with open(tu.get_file_path(), 'rb') as f:
            data = File(f)
            ffile.save(tu.upload_name, data, False)
    except:
        pass
    return ffile

def do_tmp(self, instance, modfld, value, cb):
    try:
        tu = TU.objects.get(upload_id=value)
        ffile = cb(instance, modfld, tu) if cb else None
    except TU.DoesNotExist:
        ffile = None
    else:
        tu.delete()

    file_id = "%s_%s" % (self.name, instance.pk)
    try:
        ogtu = TU.objects.get(file_id=file_id)
    except TU.DoesNotExist:
        pass
    else:
        ogtu.delete()

    return ffile

def save(self, instance, modfld, value):
    return self.do_tmp(instance, modfld, value, self.save_cb)

def del_tmp(self, instance, modfld, value):
    self.do_tmp(instance, modfld, value, None)

def bound_data(self, data, initial):
    return data

def has_changed(self, initial, data):
    if not initial:
        return data
    return initial != data

forms.py

class ImageForm(forms.ModelForm):
img_fields = []

def __init__(self, *args, **kwargs):
    super(ImageForm, self).__init__(*args, **kwargs)
    for (fld, fargs) in self.img_fields:
        self.fields[fld] = FilePondField(fld, **fargs)

def save(self, *args, **kwargs):
    commit = kwargs.get('commit', True)
    for (fld_nm, fargs) in self.img_fields:
        fld = dict([(f.name, f) for f in self._meta.model._meta.fields])[fld_nm]
        if isinstance(self.fields[fld_nm], FilePondField):
            self.fields[fld_nm] = self.fields[fld_nm].save(self.instance, fld, self.cleaned_data[fld_nm])

    return super(ImageForm, self).save(*args, **kwargs)

def del_tmp (self):
    for (fld_nm, fargs) in self.img_fields:
        fld = dict([(f.name, f) for f in self._meta.model._meta.fields])[fld_nm]
        if isinstance(self.fields[fld_nm], FilePondField):
            self.fields[fld_nm].del_tmp(self.instance, fld, self.cleaned_data[fld_nm])

My Approach:

in fields.py I import

In the function def prepare_value(self, data): and def do_tmp(self, instance, modfld, value, cb): I make the below changes

...

file_id = "%s_%s_%s" % (self.name, data.instance.pk, datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S_%f"))
...

Can someone comment on this or suggest a better alternative

Samir Tendulkar
  • 1,151
  • 3
  • 19
  • 47
  • when u upload any file, can u not name the file as `fileName_userName_timeStamp_RandomString`? this would help preventing overwrites by same as well as different user – NoobEditor Apr 22 '19 at 04:53

2 Answers2

1

Just use datetime.now() value for the file name such as below:

from datetime import datetime
open(str(datetime.now()) + ".txt", "w+")

Result: It creates a file named 2019-04-22 00:21:31.862001.txt

Jonathan Gagne
  • 4,241
  • 5
  • 18
  • 30
0

make the name a variable like this

name = "Your-General-Name-{}".format((int(time.time())))

and then put it in your loop so that the time.time() value changes each time. You obviously dont have to use time.time(). you could use datetime.datetime.now() etc. but then you'd just replace the time function.

Kaleba KB Keitshokile
  • 1,656
  • 1
  • 6
  • 12