├── demo
├── demo
│ ├── __init__.py
│ ├── urls.py
│ ├── wsgi.py
│ └── settings.py
├── filepicker_demo
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ ├── 0001_initial.py
│ │ └── 0002_auto_20150323_1549.py
│ ├── urls.py
│ ├── admin.py
│ ├── tests.py
│ ├── models.py
│ ├── templates
│ │ └── home.html
│ └── views.py
├── build
│ └── pip-delete-this-directory.txt
├── manage.py
└── templates
│ └── home.html
├── MANIFEST.in
├── django_filepicker
├── .DS_Store
├── __init__.py
├── context_processors.py
├── widgets.py
├── middleware.py
├── utils.py
├── models.py
└── forms.py
├── .gitignore
├── MANIFEST
├── setup.py
├── CHANGELOG
├── LICENSE.txt
└── README.md
/demo/demo/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include CHANGELOG
2 |
--------------------------------------------------------------------------------
/demo/filepicker_demo/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/filepicker_demo/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/django_filepicker/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/filepicker/filepicker-django/HEAD/django_filepicker/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.pyc
3 | demo/media/uploads/
4 | demo/db.sql
5 | dist/
6 | db.sqlite3
7 | .DS_STORE
8 | build
9 | django_filepicker.egg-info
10 | .idea
11 |
--------------------------------------------------------------------------------
/demo/filepicker_demo/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import patterns, include, url
2 | from django.contrib import admin
3 | from filepicker_demo.views import pick
4 |
5 |
6 | urlpatterns = patterns('',
7 | url(r'^$', pick, name='pick'),
8 | )
--------------------------------------------------------------------------------
/demo/build/pip-delete-this-directory.txt:
--------------------------------------------------------------------------------
1 | This file is placed here by pip to indicate the source was put
2 | here by pip.
3 |
4 | Once this package is successfully installed this source code will be
5 | deleted (unless you remove this file).
6 |
--------------------------------------------------------------------------------
/demo/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
7 |
8 | from django.core.management import execute_from_command_line
9 |
10 | execute_from_command_line(sys.argv)
11 |
--------------------------------------------------------------------------------
/django_filepicker/__init__.py:
--------------------------------------------------------------------------------
1 | try:
2 | from . import models
3 | from . import forms
4 | from . import middleware
5 | from . import widgets
6 | from . import context_processors
7 | except ImportError:
8 | import models
9 | import forms
10 | import middleware
11 | import widgets
12 | import context_processors
--------------------------------------------------------------------------------
/MANIFEST:
--------------------------------------------------------------------------------
1 | # file GENERATED by distutils, do NOT edit
2 | CHANGELOG
3 | setup.py
4 | django_filepicker/__init__.py
5 | django_filepicker/context_processors.py
6 | django_filepicker/forms.py
7 | django_filepicker/middleware.py
8 | django_filepicker/models.py
9 | django_filepicker/utils.py
10 | django_filepicker/widgets.py
11 |
--------------------------------------------------------------------------------
/django_filepicker/context_processors.py:
--------------------------------------------------------------------------------
1 | from django.utils.safestring import mark_safe
2 | from .widgets import JS_URL
3 |
4 | def js(request):
5 | #Defines a {{FILEPICKER_JS}} tag that inserts the filepicker javascript library
6 | return {"FILEPICKER_JS":
7 | mark_safe('' % JS_URL)}
8 |
--------------------------------------------------------------------------------
/demo/demo/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import patterns, include, url
2 | from django.contrib import admin
3 |
4 | urlpatterns = patterns('',
5 | # Examples:
6 | # url(r'^$', 'demo.views.home', name='home'),
7 | # url(r'^blog/', include('blog.urls')),
8 | url(r'^$', include('filepicker_demo.urls', namespace='demo')),
9 | url(r'^admin/', include(admin.site.urls)),
10 | )
11 |
--------------------------------------------------------------------------------
/demo/demo/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for demo project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
12 |
13 | from django.core.wsgi import get_wsgi_application
14 | application = get_wsgi_application()
15 |
--------------------------------------------------------------------------------
/demo/filepicker_demo/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from models import FileModel, BasicFilesModel
3 |
4 |
5 | class BasicFilesModelAdmin(admin.ModelAdmin):
6 | pass
7 |
8 |
9 | class FileModelAdmin(admin.ModelAdmin):
10 | readonly_fields = ('image_tag',)
11 | list_display = ('__unicode__', 'image_tag')
12 |
13 |
14 | admin.site.register(FileModel, FileModelAdmin)
15 | admin.site.register(BasicFilesModel, BasicFilesModelAdmin)
--------------------------------------------------------------------------------
/demo/filepicker_demo/tests.py:
--------------------------------------------------------------------------------
1 | """
2 | This file demonstrates writing tests using the unittest module. These will pass
3 | when you run "manage.py test".
4 |
5 | Replace this with more appropriate tests for your application.
6 | """
7 |
8 | from django.test import TestCase
9 |
10 |
11 | class SimpleTest(TestCase):
12 | def test_basic_addition(self):
13 | """
14 | Tests that 1 + 1 always equals 2.
15 | """
16 | self.assertEqual(1 + 1, 2)
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | try:
2 | from setuptools import setup
3 | except ImportError:
4 | from distutils.core import setup
5 |
6 | setup(
7 | name='django-filepicker',
8 | version='0.2.3',
9 | description='Official Filepicker Django Library',
10 | author='Filepicker.io',
11 | author_email='contact@filepicker.io',
12 | url='http://developers.filepicker.io/',
13 | packages=['django_filepicker'],
14 | install_requires=['django >= 1.3','requests'],
15 | license="BSD",
16 | zip_safe=False,
17 | )
18 |
--------------------------------------------------------------------------------
/CHANGELOG:
--------------------------------------------------------------------------------
1 | Version 0.2.3 - Jul 15 2015
2 | - Fixed problem of missing request headers
3 |
4 | Version 0.2.1 - Sep 26 2014
5 | - Updated the demo app
6 | - Updated .gitignore
7 |
8 | Version 0.2.0 - Sep 26 2014
9 | - Updated the library to work with Python 3
10 | - Rewritten the demo app to Django 1.7
11 |
12 | Version 0.1.5 - Aug 27 2013
13 | - Added South introspection rule
14 |
15 | Version 0.1.2 - Oct 2 2012
16 | - Patched middleware, FPUrlField
17 | - Added middleware support for multiple files
18 | - Added FPUrlField
19 |
20 | Version 0.1.1 - Sept 30 2012
21 | - Updated widgets for services field
22 | - Added a "services" attribute to the FPFileField
23 |
24 | Version 0.1
25 | - Basic hooks via FPFileField in models and forms
26 | - Filepicker widget
27 | - Filepicker middleware
28 |
--------------------------------------------------------------------------------
/demo/filepicker_demo/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models, migrations
5 | import django_filepicker.models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | ]
12 |
13 | operations = [
14 | migrations.CreateModel(
15 | name='TestModel',
16 | fields=[
17 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
18 | ('text', models.CharField(max_length=64)),
19 | ('fpfile', django_filepicker.models.FPFileField(upload_to=b'uploads')),
20 | ],
21 | options={
22 | },
23 | bases=(models.Model,),
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/django_filepicker/widgets.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.forms import widgets
3 |
4 | #JS_URL is the url to the filepicker.io javascript library
5 | JS_VERSION = getattr(settings, "FILEPICKER_JS_VERSION", 1)
6 | JS_URL = "//api.filepicker.io/v%d/filepicker.js" % (JS_VERSION)
7 |
8 | INPUT_TYPE = getattr(settings, "FILEPICKER_INPUT_TYPE", "filepicker-dragdrop")
9 |
10 | class FPFileWidget(widgets.Input):
11 | input_type = INPUT_TYPE
12 | needs_multipart_form = False
13 |
14 | def value_from_datadict_old(self, data, files, name):
15 | #If we are using the middleware, then the data will already be
16 | #in FILES, if not it will be in POST
17 | if name not in data:
18 | return super(FPFileWidget, self).value_from_datadict(
19 | data, files, name)
20 |
21 | return data
22 |
23 | class Media:
24 | js = (JS_URL,)
25 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2012 Filepicker.io
2 | https://filepicker.io/
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/demo/filepicker_demo/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django import forms
3 | import django_filepicker
4 |
5 |
6 | class BasicFilesModel(models.Model):
7 | text = models.CharField(max_length=64)
8 |
9 | def __unicode__(self):
10 | return 'Files chain {}. ID:{}'.format(self.text, self.pk)
11 |
12 |
13 | class FileModel(models.Model):
14 | mid = models.ForeignKey(BasicFilesModel)
15 | fpfile = django_filepicker.models.FPFileField(
16 | upload_to='uploads', additional_params={'data-fp-multiple': 'true'})
17 | fpurl = models.URLField(max_length=255, null=True, blank=True)
18 |
19 | def __unicode__(self):
20 | return 'File from chain {}:id-{}. ID:{}'.format(
21 | self.mid.text, self.mid.pk, self.pk)
22 |
23 | def image_tag(self):
24 | return u'' % self.fpurl
25 | image_tag.short_description = 'Image'
26 | image_tag.allow_tags = True
27 |
28 |
29 | class BasicFilesForm(forms.ModelForm):
30 | class Meta:
31 | model = BasicFilesModel
32 | fields = ['text']
33 |
34 |
35 | class FileForm(forms.ModelForm):
36 | class Meta:
37 | model = FileModel
38 | fields = ['fpfile']
--------------------------------------------------------------------------------
/demo/templates/home.html:
--------------------------------------------------------------------------------
1 |
2 |
{{message}}
{%endif%} 9 | 14 |import django_filepicker 16 | 17 | class TestModel(models.Model): 18 | text = models.CharField(max_length=64) 19 | fpfile = django_filepicker.models.FPFileField(upload_to='uploads') 20 |21 |
form = models.TestModelForm(request.POST, request.FILES) 23 | if form.is_valid(): 24 | #Save will read the data and upload it to the location defined in TestModel 25 | form.save()26 | 27 |
Code available on GitHub at https://github.com/Filepicker/django-filepicker.
29 |For more info and to get an api key, check out Filepicker.io.
30 | 31 | 32 | -------------------------------------------------------------------------------- /demo/filepicker_demo/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |{{message}}
{%endif%} 9 | 15 |import django_filepicker 17 | 18 | class TestModel(models.Model): 19 | text = models.CharField(max_length=64) 20 | fpfile = django_filepicker.models.FPFileField(upload_to='uploads') 21 |22 |
form = models.TestModelForm(request.POST, request.FILES) 24 | if form.is_valid(): 25 | #Save will read the data and upload it to the location defined in TestModel 26 | form.save()27 | 28 |
Code available on GitHub at https://github.com/Filepicker/django-filepicker.
30 |For more info and to get an api key, check out Filepicker.io.
31 | 32 | 33 | -------------------------------------------------------------------------------- /demo/filepicker_demo/migrations/0002_auto_20150323_1549.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | import django_filepicker.models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('filepicker_demo', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='BasicFilesModel', 17 | fields=[ 18 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 19 | ('text', models.CharField(max_length=64)), 20 | ], 21 | options={ 22 | }, 23 | bases=(models.Model,), 24 | ), 25 | migrations.CreateModel( 26 | name='FileModel', 27 | fields=[ 28 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 29 | ('fpfile', django_filepicker.models.FPFileField(upload_to=b'uploads')), 30 | ('fpurl', models.URLField(max_length=255, null=True, blank=True)), 31 | ('mid', models.ForeignKey(to='filepicker_demo.BasicFilesModel')), 32 | ], 33 | options={ 34 | }, 35 | bases=(models.Model,), 36 | ), 37 | migrations.DeleteModel( 38 | name='TestModel', 39 | ), 40 | ] 41 | -------------------------------------------------------------------------------- /django_filepicker/middleware.py: -------------------------------------------------------------------------------- 1 | try: 2 | from .utils import FilepickerFile 3 | except ImportError: 4 | from utils import FilepickerFile 5 | 6 | class URLFileMapperMiddleware(object): 7 | """ 8 | This middleware will take any Filepicker.io urls that are posted to the server via a POST 9 | and put a matching File object into request.FILES. This way, if you're used to grabbing files out of 10 | request.FILES, you don't have to change your backend code when using the filepicker.io widgets. 11 | 12 | This middleware is rather agressive in that it will automatically fetch any and all filepicker 13 | urls passed to the server, so if you are already processing the files via FPFileField or similar 14 | this functionality is redundant 15 | 16 | Note that the original filepicker.io url will still be available in POST if you need it. 17 | """ 18 | def process_request(self, request): 19 | #Iterate over GET or POST data, search for filepicker.io urls 20 | for key, val in list(request.POST.items()): 21 | try: 22 | fp = FilepickerFile(val) 23 | except ValueError: 24 | pass 25 | else: 26 | splits = val.split(",") 27 | if key in request.FILES: 28 | request.FILES.setlist(key, 29 | request.FILES.getlist(key) + fp.get_file()) 30 | else: 31 | request.FILES.setlist(key, fp.get_file()) 32 | -------------------------------------------------------------------------------- /demo/filepicker_demo/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | try: 4 | from .models import BasicFilesForm, FileForm 5 | except ImportError: 6 | from models import BasicFilesForm, FileForm 7 | 8 | 9 | def pick(request): 10 | message = None 11 | basic_form = BasicFilesForm() 12 | form = FileForm() 13 | 14 | if request.method == "POST": 15 | post = request.POST.dict() 16 | basic_form = BasicFilesForm(post) 17 | if basic_form.is_valid(): 18 | f = basic_form.save() 19 | post['mid_id'] = f.id 20 | else: 21 | message = 'Invalid form' 22 | 23 | files_links = request.POST['fpfile'].split(',') 24 | if post.get('mid_id', None): 25 | for i, f in enumerate(request.FILES.getlist("fpfile")): 26 | form = FileForm(post) 27 | if form.is_valid(): 28 | fp = form.save(commit=False) 29 | fp.fpfile = f 30 | fp.fpurl = files_links[i] 31 | fp.mid_id = post.get('mid_id') 32 | fp.save() 33 | else: 34 | message = "Invalid form" 35 | files = ", ".join([str(f) for f in request.FILES.getlist("fpfile")]) 36 | message = "Save successful. URL for {0}: {1}".format( 37 | files, request.POST["fpfile"]) if not message else message 38 | 39 | return render(request, "home.html", {'form': form, 'message': message, 'basic_form': basic_form}) -------------------------------------------------------------------------------- /demo/demo/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for demo project. 3 | 4 | For more information on this file, see 5 | https://docs.djangoproject.com/en/1.7/topics/settings/ 6 | 7 | For the full list of settings and their values, see 8 | https://docs.djangoproject.com/en/1.7/ref/settings/ 9 | """ 10 | 11 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 12 | import os 13 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 14 | 15 | CWD = os.getcwd() 16 | 17 | # Quick-start development settings - unsuitable for production 18 | # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ 19 | 20 | # SECURITY WARNING: keep the secret key used in production secret! 21 | SECRET_KEY = '&v@4o*w1ocho4anvc-z5u-zkgk33k7a5xi)f%2jh4!z*vdz2*a' 22 | 23 | # SECURITY WARNING: don't run with debug turned on in production! 24 | DEBUG = True 25 | 26 | TEMPLATE_DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | FILEPICKER_API_KEY = 'REPLACE_ME' 31 | 32 | MEDIA_ROOT = os.path.join(CWD, 'media') 33 | 34 | # Application definition 35 | 36 | INSTALLED_APPS = ( 37 | 'django.contrib.admin', 38 | 'django.contrib.auth', 39 | 'django.contrib.contenttypes', 40 | 'django.contrib.sessions', 41 | 'django.contrib.messages', 42 | 'django.contrib.staticfiles', 43 | 'filepicker_demo' 44 | ) 45 | 46 | MIDDLEWARE_CLASSES = ( 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | #New in Django 1.7 52 | #'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 53 | 'django.contrib.messages.middleware.MessageMiddleware', 54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 55 | #This optional middleware takes all filepicker urls and puts the data into request.FILES 56 | 'django_filepicker.middleware.URLFileMapperMiddleware', 57 | ) 58 | 59 | ROOT_URLCONF = 'demo.urls' 60 | 61 | WSGI_APPLICATION = 'demo.wsgi.application' 62 | 63 | 64 | # Database 65 | # https://docs.djangoproject.com/en/1.7/ref/settings/#databases 66 | 67 | DATABASES = { 68 | 'default': { 69 | 'ENGINE': 'django.db.backends.sqlite3', 70 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 71 | } 72 | } 73 | 74 | # Internationalization 75 | # https://docs.djangoproject.com/en/1.7/topics/i18n/ 76 | 77 | LANGUAGE_CODE = 'en-us' 78 | 79 | TIME_ZONE = 'UTC' 80 | 81 | USE_I18N = True 82 | 83 | USE_L10N = True 84 | 85 | USE_TZ = True 86 | 87 | 88 | # Static files (CSS, JavaScript, Images) 89 | # https://docs.djangoproject.com/en/1.7/howto/static-files/ 90 | 91 | STATIC_URL = '/static/' 92 | -------------------------------------------------------------------------------- /django_filepicker/utils.py: -------------------------------------------------------------------------------- 1 | import re 2 | import os 3 | import requests 4 | import tempfile 5 | from django.core.files import File 6 | 7 | 8 | class FilepickerFile(File): 9 | filepicker_url_regex = re.compile( 10 | r'https?:\/\/www.filepicker.io\/api\/file\/.*') 11 | 12 | def __init__(self, url): 13 | if not self.filepicker_url_regex.match(url): 14 | raise ValueError('Not a filepicker.io URL: %s' % url) 15 | self.url = url 16 | 17 | def get_file(self, additional_params=None): 18 | ''' 19 | Downloads the file from filepicker.io and returns a 20 | Django File wrapper object. 21 | additional_params should include key/values such as: 22 | { 23 | 'data-fp-signature': HEXDIGEST, 24 | 'data-fp-policy': HEXDIGEST, 25 | } 26 | (in other words, parameters should look like additional_params 27 | of the models) 28 | ''' 29 | # clean up any old downloads that are still hanging around 30 | self.cleanup() 31 | 32 | # Fetch any fields possibly required for fetching files for reading. 33 | query_params = {} 34 | 35 | if additional_params: 36 | for field in ('policy','signature'): 37 | longfield = 'data-fp-{0}'.format(field) 38 | if longfield in additional_params: 39 | query_params[field] = additional_params[longfield] 40 | 41 | # iterate through one or more file urls 42 | result = list() 43 | for url in self.url.split(","): 44 | # Append the fields as GET query parameters to the URL in data. 45 | r = requests.get(url, params=query_params, stream=True) 46 | header = r.headers 47 | name = '' 48 | disposition = header.get('Content-Disposition') 49 | if disposition: 50 | name = disposition.rpartition("filename=")[2].strip('" ') 51 | filename = header.get('X-File-Name') 52 | if filename: 53 | name = filename 54 | 55 | # Create a temporary file to save to it later 56 | tmp = tempfile.NamedTemporaryFile(mode='w+b') 57 | for chunk in r.iter_content(chunk_size=1024): 58 | if chunk: 59 | tmp.write(chunk) # Write the chunk 60 | tmp.flush() 61 | 62 | # initialize File components of this object 63 | file = File(tmp, name=name) 64 | result.append(file) 65 | return result 66 | 67 | def cleanup(self): 68 | ''' 69 | Removes any downloaded objects and closes open files. 70 | ''' 71 | # self.file comes from Django File 72 | if hasattr(self, 'file'): 73 | if not self.file.closed: 74 | self.file.close() 75 | delattr(self, 'file') 76 | 77 | if hasattr(self, 'filename'): 78 | # the file might have been moved in the meantime so 79 | # check first 80 | if os.path.exists(self.filename): 81 | os.remove(self.filename) 82 | delattr(self, 'filename') 83 | 84 | def __enter__(self): 85 | ''' 86 | Allow FilepickerFile to be used as a context manager as such: 87 | 88 | with FilepickerFile(url) as f: 89 | model.field.save(f.name, f.) 90 | ''' 91 | self.get_file() 92 | # call Django's File context manager 93 | return super(FilepickerFile, self).__enter__() 94 | 95 | def __exit__(self, *args): 96 | # call Django's File context manager 97 | super(FilepickerFile, self).__exit__(*args) 98 | self.cleanup() 99 | 100 | def __del__(self): 101 | self.cleanup() 102 | -------------------------------------------------------------------------------- /django_filepicker/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.utils.translation import ugettext_lazy 3 | 4 | try: 5 | from . import forms 6 | except ImportError: 7 | import forms 8 | 9 | class FPUrlField(models.URLField): 10 | description = ugettext_lazy("A URL field for storing FilePicker.IO urls that works with the FilePicker widget") 11 | 12 | def __init__(self, *args, **kwargs): 13 | """ 14 | Initializes the Filepicker url field. 15 | Valid arguments: 16 | * apikey. This string is required if it isn't set as settings.FILEPICKER_API_KEY 17 | * mimetypes. Optional, the allowed mimetypes for files. Defaults to "*/*" (all files) 18 | * services. Optional, the allowed services to pull from. 19 | * additional_params. Optional, additional parameters to be applied. 20 | """ 21 | self.apikey = kwargs.pop("apikey", None) 22 | self.mimetypes = kwargs.pop("mimetypes", None) 23 | self.services = kwargs.pop("services", None) 24 | self.additional_params=kwargs.pop("additional_params", None) 25 | 26 | super(FPUrlField, self).__init__(*args, **kwargs) 27 | 28 | def formfield(self, **kwargs): 29 | defaults = {'form_class': forms.FPUrlField, 30 | 'max_length': self.max_length} 31 | 32 | if 'initial' in kwargs: 33 | defaults['required'] = False 34 | 35 | if self.apikey: 36 | defaults['apikey'] = self.apikey 37 | if self.mimetypes: 38 | defaults['mimetypes'] = self.mimetypes 39 | if self.services: 40 | defaults['services'] = self.services 41 | if self.additional_params: 42 | defaults['additional_params'] = self.additional_params 43 | 44 | defaults.update(kwargs) 45 | return super(FPUrlField, self).formfield(**defaults) 46 | 47 | try: 48 | # For South. See: http://south.readthedocs.org/en/latest/customfields.html#extending-introspection 49 | from south.modelsinspector import add_introspection_rules 50 | add_introspection_rules([], ["django_filepicker\.models\.FPUrlField"]) 51 | except ImportError: 52 | pass 53 | 54 | 55 | class FPFileField(models.FileField): 56 | description = ugettext_lazy("A File selected using Filepicker.io") 57 | 58 | def __init__(self, *args, **kwargs): 59 | """ 60 | Initializes the Filepicker file field. 61 | Valid arguments: 62 | * apikey. This string is required if it isn't set as settings.FILEPICKER_API_KEY 63 | * mimetypes. Optional, the allowed mimetypes for files. Defaults to "*/*" (all files) 64 | * services. Optional, the allowed services to pull from. 65 | * additional_params. Optional, additional parameters to be applied. 66 | """ 67 | self.apikey = kwargs.pop("apikey", None) 68 | self.mimetypes = kwargs.pop("mimetypes", None) 69 | self.services = kwargs.pop("services", None) 70 | self.additional_params=kwargs.pop("additional_params", None) 71 | 72 | super(FPFileField, self).__init__(*args, **kwargs) 73 | 74 | def formfield(self, **kwargs): 75 | defaults = {'form_class': forms.FPFileField, 76 | 'max_length': self.max_length} 77 | 78 | if 'initial' in kwargs: 79 | defaults['required'] = False 80 | 81 | if self.apikey: 82 | defaults['apikey'] = self.apikey 83 | if self.mimetypes: 84 | defaults['mimetypes'] = self.mimetypes 85 | if self.services: 86 | defaults['services'] = self.services 87 | if self.additional_params: 88 | defaults['additional_params'] = self.additional_params 89 | 90 | defaults.update(kwargs) 91 | return super(FPFileField, self).formfield(**defaults) 92 | 93 | try: 94 | # For South. See: http://south.readthedocs.org/en/latest/customfields.html#extending-introspection 95 | from south.modelsinspector import add_introspection_rules 96 | add_introspection_rules([], ["django_filepicker\.models\.FPFileField"]) 97 | except ImportError: 98 | pass 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | django-filepicker 2 | ================= 3 |  4 |  5 | 6 | A django plugin to make integrating with Filepicker.io even easier 7 | 8 | ##Installation 9 | 10 | 1. Install the python package: 11 | 12 | pip install django-filepicker 13 | 14 | 2. Add your file picker api key to your settings.py file. You api key can be 15 | found in the [developer portal](https://developers.inkfilepicker.com/apps/). 16 | 17 | FILEPICKER_API_KEY =