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
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
Post a Comment