0

I'm trying to save files in a FTP server. At first, I had this error and that link was useful as minimal example too. It worked for me locally, but after I deployed it on heroku, I don't know what I changed but it stopped working and is throwing this error:

NotImplementedError at /app/new-prof

subclasses of Storage must provide an exists() method

Here is the ftp.py code, an exists method is on line ~200. Useful code (if more needed, say):

settings.py

Installed Applications:
[...
 'django.contrib.staticfiles',
 'directorio.apps.myapp',
 'django_cleanup',
 'storages']

FTP_USER = os.environ['FTP_USER']
FTP_PASS = os.environ['FTP_PASS']
FTP_PORT = os.environ['FTP_PORT']
DEFAULT_FILE_STORAGE = 'storages.backends.ftp.FTPStorage'
FTP_STORAGE_LOCATION = 'ftp://' + FTP_USER + ':' + FTP_PASS + '@<server>:' + FTP_PORT

models.py

from app.ftp import FTPStorage
fs = FTPStorage()

def upload_path_handler(instance, filename): 
     return "{id_p}/{f}".format(id_p=instance.id, f=filename)

class Professor(models.Model):
  name = models.CharField(max_length=100)
  email = models.EmailField(max_length=75)
  foto = models.ImageField(upload_to=upload_path_handler, null=True, blank=True, storage=fs)
  cv = models.FileField(upload_to=upload_path_handler, null=True, blank=True, storage=fs)

forms.py

class ProfessorForm(forms.ModelForm):
  class Meta:
      model = Professor
      exclude = ['name']

views.py

def nuevo_profesor(request):

if request.method == 'POST':
    pform = ProfessorForm(request.POST, request.FILES)

    if pform.is_valid():
        new_prof = pform.save()

        return redirect('app:professor', new_prof.id)

Traceback

NotImplementedError

subclasses of Storage must provide an exists() method

Request Method: POST

Request URL: http://127.0.0.1:8000/

Django Version: 1.9.2

Exception Type: NotImplementedError

Exception Value: subclasses of Storage must provide an exists() method

Exception Location: C:\Users\myuser\Envs\iepenv\lib\site-packages\django\core\files\storage.py in exists, line 130

Python Executable: C:\Users\myuser\Envs\iepenv\Scripts\python.exe

Python Version: 3.4.3

Django Version: 1.9.2

Full Traceback

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\core\handlers\base.py" in get_response 149. response = self.process_exception_by_middleware(e, request)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\core\handlers\base.py" in get_response 147. response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view 23. return view_func(request, *args, **kwargs)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view 23. return view_func(request, *args, **kwargs)

File "C:\Users\myuser\Desktop\Cosas\directorio\iep\directorio\views.py" in new_prof 305. new_prof = pform.save()

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\forms\models.py" in save 451. self.instance.save()

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\base.py" in save 700. force_update=force_update, update_fields=update_fields)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\base.py" in save_base 728. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\base.py" in _save_table 812. result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\base.py" in _do_insert 851. using=using, raw=raw)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\manager.py" in manager_method 122. return getattr(self.get_queryset(), name)(*args, **kwargs)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\query.py" in _insert 1039. return query.get_compiler(using=using).execute_sql(return_id)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\sql\compiler.py" in execute_sql 1059. for sql, params in self.as_sql():

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\sql\compiler.py" in as_sql 1019. for obj in self.query.objs

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\sql\compiler.py" in 1019. for obj in self.query.objs

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\sql\compiler.py" in 1018. [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\sql\compiler.py" in pre_save_val 968. return field.pre_save(obj, add=True)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\fields\files.py" in pre_save 311. file.save(file.name, file, save=False)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\db\models\fields\files.py" in save 93. self.name = self.storage.save(name, content, max_length=self.field.max_length)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\core\files\storage.py" in save 53. name = self.get_available_name(name, max_length=max_length)

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\core\files\storage.py" in get_available_name 89. while self.exists(name) or (max_length and len(name) > max_length):

File "C:\Users\myuser\Envs\iepvenv\lib\site-packages\django\core\files\storage.py" in exists 130. raise NotImplementedError('subclasses of Storage must provide an exists() method')

Exception Type: NotImplementedError at / Exception Value: subclasses of Storage must provide an exists() method

Any thoughts? Or could you suggest me other ways to do it?

Community
  • 1
  • 1
josemfc
  • 108
  • 1
  • 8
  • I haven't explained correctly, it stopped working on dev too. I'll edit it. Anyway I've checked that they are running the same version. – josemfc Mar 07 '16 at 11:28

1 Answers1

0

Solved!

Due to an issue, I added a @deconstructible class decorator in ftp.py, and I wasn't adding it correctly. I added the example function explained here at the end of the code, but the decorator must be written just before the 'class FTPStorage(Storage)', (line 31 in the ftp.py I link in the original post).

Community
  • 1
  • 1
josemfc
  • 108
  • 1
  • 8