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?