python - Django file upload with FTP backend -


i want upload files based on example need minimal django file upload example, want store files not locally, on server use of ftp.

i have been trying this code work, looks simple enough, keep getting importerror: no module named ftpstorage when run python manage.py runserver

i have looked @ multiple repos , searched site no avail. suppose it's simple task, can't seem work.

thanks.

folder structure

folder_structure

settings.py

"""  django settings myproject project.  generated 'django-admin startproject' using django 1.8.  more information on file, see https://docs.djangoproject.com/en/1.8/topics/settings/  full list of settings , values, see https://docs.djangoproject.com/en/1.8/ref/settings/ """  # build paths inside project this: os.path.join(base_dir, ...) import os  # build paths inside project this: os.path.join(base_dir, ...) base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))   # quick-start development settings - unsuitable production # see https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/  # security warning: keep secret key used in production secret! secret_key = '-q@x+fbn4vl-+qs!*a=+(u%j1w76z_(7re-1*b+yb&a+rj=-&+'  # security warning: don't run debug turned on in production! debug = true  allowed_hosts = []   # application definition  installed_apps = (     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',     'myproject.myapp',     'storages', )  middleware_classes = (     'django.contrib.sessions.middleware.sessionmiddleware',     'django.middleware.common.commonmiddleware',     'django.middleware.csrf.csrfviewmiddleware',     'django.contrib.auth.middleware.authenticationmiddleware',     'django.contrib.auth.middleware.sessionauthenticationmiddleware',     'django.contrib.messages.middleware.messagemiddleware',     'django.middleware.clickjacking.xframeoptionsmiddleware',     'django.middleware.security.securitymiddleware', )  root_urlconf = 'myproject.urls'  templates = [     {         'backend': 'django.template.backends.django.djangotemplates',         'dirs': [             os.path.join(base_dir, 'myproject', 'myapp', 'templates')         ],         'app_dirs': true,         'options': {             'context_processors': [                 # insert template_context_processors here or use                 # list if haven't customized them:                 'django.contrib.auth.context_processors.auth',                 'django.template.context_processors.debug',                 'django.template.context_processors.i18n',                 'django.template.context_processors.media',                 'django.template.context_processors.static',                 'django.template.context_processors.tz',                 'django.contrib.messages.context_processors.messages',             ],         },     }, ]  wsgi_application = 'myproject.wsgi.application'   # database # https://docs.djangoproject.com/en/1.8/ref/settings/#databases  databases = {     'default': {         'engine': 'django.db.backends.sqlite3',         'name': os.path.join(base_dir, 'db.sqlite3'),     } }   # internationalization # https://docs.djangoproject.com/en/1.8/topics/i18n/  language_code = 'en-us'  time_zone = 'utc'  use_i18n = true  use_l10n = true  use_tz = true   media_root = os.path.join(base_dir, 'media') media_url = '/media/'  # static files (css, javascript, images) # https://docs.djangoproject.com/en/1.8/howto/static-files/ static_url = '/static/'  default_file_storage = 'storages.backends.ftp.ftpstorage' ftp_storage_location = 'ftp://<user>:<pass>@<host>:<port>/[path]' 

models.py

# -*- coding: utf-8 -*- django.db import models ftpstorage import ftpstorage  fs = ftpstorage() class ftptest(models.model):     file = models.filefield(upload_to='srv/ftp/', storage=fs)  class document(models.model):     docfile = models.filefield(upload_to='documents') 

ftp.py

# ftp storage class django pluggable storage system. # author: rafal jonca <jonca.rafal@gmail.com> # license: mit # comes http://www.djangosnippets.org/snippets/1269/ # # usage: # # add below settings.py: # ftp_storage_location = '[a]ftp://<user>:<pass>@<host>:<port>/[path]' # # in models.py can write: # ftpstorage import ftpstorage # fs = ftpstorage() # class ftptest(models.model): #     file = models.filefield(upload_to='a/b/c/', storage=fs)  import os datetime import datetime import ftplib  django.conf import settings django.core.files.base import file django.core.exceptions import improperlyconfigured  storages.compat import urlparse, bytesio, storage   class ftpstorageexception(exception):     pass   class ftpstorage(storage):     """ftp storage class django pluggable storage system."""      def __init__(self, location=settings.ftp_storage_location,                  base_url=settings.media_url):         self._config = self._decode_location(location)         self._base_url = base_url         self._connection = none      def _decode_location(self, location):         """return splitted configuration data location."""         splitted_url = urlparse.urlparse(location)         config = {}          if splitted_url.scheme not in ('ftp', 'aftp'):             raise improperlyconfigured(                 'ftpstorage works ftp protocol!'             )         if splitted_url.hostname == '':             raise improperlyconfigured('you must @ least provide hostname!')          if splitted_url.scheme == 'aftp':             config['active'] = true         else:             config['active'] = false         config['path'] = splitted_url.path         config['host'] = splitted_url.hostname         config['user'] = splitted_url.username         config['passwd'] = splitted_url.password         config['port'] = int(splitted_url.port)          return config      def _start_connection(self):         # check if connection still alive , if not, drop it.         if self._connection not none:             try:                 self._connection.pwd()             except ftplib.all_errors:                 self._connection = none          # real reconnect         if self._connection none:             ftp = ftplib.ftp()             try:                 ftp.connect(self._config['host'], self._config['port'])                 ftp.login(self._config['user'], self._config['passwd'])                 if self._config['active']:                     ftp.set_pasv(false)                 if self._config['path'] != '':                     ftp.cwd(self._config['path'])                 self._connection = ftp                 return             except ftplib.all_errors:                 raise ftpstorageexception(                     'connection or login error using data %s'                     % repr(self._config)                 )      def disconnect(self):         self._connection.quit()         self._connection = none      def _mkremdirs(self, path):         pwd = self._connection.pwd()         path_splitted = path.split('/')         path_part in path_splitted:             try:                 self._connection.cwd(path_part)             except:                 try:                     self._connection.mkd(path_part)                     self._connection.cwd(path_part)                 except ftplib.all_errors:                     raise ftpstorageexception(                         'cannot create directory chain %s' % path                     )         self._connection.cwd(pwd)         return      def _put_file(self, name, content):         # connection must open!         try:             self._mkremdirs(os.path.dirname(name))             pwd = self._connection.pwd()             self._connection.cwd(os.path.dirname(name))             self._connection.storbinary('stor ' + os.path.basename(name),                                         content.file,                                         content.default_chunk_size)             self._connection.cwd(pwd)         except ftplib.all_errors:             raise ftpstorageexception('error writing file %s' % name)      def _open(self, name, mode='rb'):         remote_file = ftpstoragefile(name, self, mode=mode)         return remote_file      def _read(self, name):         memory_file = bytesio()         try:             pwd = self._connection.pwd()             self._connection.cwd(os.path.dirname(name))             self._connection.retrbinary('retr ' + os.path.basename(name),                                         memory_file.write)             self._connection.cwd(pwd)             return memory_file         except ftplib.all_errors:             raise ftpstorageexception('error reading file %s' % name)      def _save(self, name, content):         content.open()         self._start_connection()         self._put_file(name, content)         content.close()         return name      def _get_dir_details(self, path):         # connection must open!         try:             lines = []             self._connection.retrlines('list ' + path, lines.append)             dirs = {}             files = {}             line in lines:                 words = line.split()                 if len(words) < 6:                     continue                 if words[-2] == '->':                     continue                 if words[0][0] == 'd':                     dirs[words[-1]] = 0                 elif words[0][0] == '-':                     files[words[-1]] = int(words[-5])             return dirs, files         except ftplib.all_errors:             raise ftpstorageexception('error getting listing %s' % path)      def modified_time(self, name):         self._start_connection()         resp = self._connection.sendcmd('mdtm ' + name)         if resp[:3] == '213':             s = resp[3:].strip()             # workaround broken ftp servers returning responses             # starting e.g. 1904... instead of 2004...             if len(s) == 15 , s[:2] == '19':                 s = str(1900 + int(s[2:5])) + s[5:]             return datetime.strptime(s, '%y%m%d%h%m%s')         raise ftpstorageexception(                 'error getting modification time of file %s' % name         )      def listdir(self, path):         self._start_connection()         try:             dirs, files = self._get_dir_details(path)             return dirs.keys(), files.keys()         except ftpstorageexception:             raise      def delete(self, name):         if not self.exists(name):             return         self._start_connection()         try:             self._connection.delete(name)         except ftplib.all_errors:             raise ftpstorageexception('error when removing %s' % name)      def exists(self, name):         self._start_connection()         try:             nlst = self._connection.nlst(                 os.path.dirname(name) + '/'             )             if name in nlst or os.path.basename(name) in nlst:                 return true             else:                 return false         except ftplib.error_temp:             return false         except ftplib.error_perm:             # error_perm: 550 can't find file             return false         except ftplib.all_errors:             raise ftpstorageexception('error when testing existence of %s'                                       % name)      def size(self, name):         self._start_connection()         try:             dirs, files = self._get_dir_details(os.path.dirname(name))             if os.path.basename(name) in files:                 return files[os.path.basename(name)]             else:                 return 0         except ftpstorageexception:             return 0      def url(self, name):         if self._base_url none:             raise valueerror("this file not accessible via url.")         return urlparse.urljoin(self._base_url, name).replace('\\', '/')   class ftpstoragefile(file):     def __init__(self, name, storage, mode):         self.name = name         self._storage = storage         self._mode = mode         self._is_dirty = false         self.file = bytesio()         self._is_read = false      @property     def size(self):         if not hasattr(self, '_size'):             self._size = self._storage.size(self.name)         return self._size      def read(self, num_bytes=none):         if not self._is_read:             self._storage._start_connection()             self.file = self._storage._read(self.name)             self._is_read = true          return self.file.read(num_bytes)      def write(self, content):         if 'w' not in self._mode:             raise attributeerror("file opened read-only access.")         self.file = bytesio(content)         self._is_dirty = true         self._is_read = true      def close(self):         if self._is_dirty:             self._storage._start_connection()             self._storage._put_file(self.name, self)             self._storage.disconnect()         self.file.close() 

it looks import wrong. if file named ftp.py import should be:

from ftp import ftpstorage 

depending on file relatively pythonpath might need add more, e.g.:

from your_app.ftp import ... 

Comments