Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Cleanup and preparing for release

  • Loading branch information...
commit 887d55922a272830c232af0c01db9fd0f485d994 1 parent 92a287e
@brettcvz brettcvz authored
View
21 LICENSE.txt
@@ -0,0 +1,21 @@
+Copyright 2012 Filepicker.io
+https://filepicker.io/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
34 README.md
@@ -1,4 +1,36 @@
django-filepicker
=================
-A django plugin to make integrating with Filepicker.io even easier
+A django plugin to make integrating with Filepicker.io even easier
+
+##Demo
+To see how all the pieces come together, see the example code in demo/, which you can run with the standard
+`python manage.py runserver` command
+
+###models.py
+ import django_filepicker
+ class TestModel(models.Model):
+ #FPFileField is a field that will render as a filepicker dragdrop widget, but
+ #When accessed will provide a File-like interface (so you can do fpfile.read(), for instance)
+ fpfile = django_filepicker.models.FPFileField(upload_to='uploads')
+
+###views.py
+ #building the form - automagically turns the uploaded fpurl into a File object
+ form = models.TestModelForm(request.POST, request.FILES)
+ if form.is_valid():
+ #Save will read the data and upload it to the location defined in TestModel
+ form.save()
+
+##Components
+###Models
+The filepicker django library defines the `FPFileField` model field so you can get all the benefits of using Filepicker.io as a drop-in replacement for the standard django `FileField`. No need to change any of your view logic.
+
+###Forms
+Similarly with the `FPFileField` for models, the filepicker django library defines a `FPFileField` for forms as well, that likewise serves as a drop-in replacement for the standard django `FileField`
+
+###Middleware
+Also included is a middleware library that will take any Filepicker.io urls passed to the server, download the contents, and place the result in request.FILES. This way, you can keep your backend code for handling file uploads the same as before while adding all the front-end magic that Filepicker.io provides
+
+If you have any questions, don't hesitate to reach out at [contact@filepicker.io](mailto:contact@filepicker.io). For more information, see [https://filepicker.io](https://www.filepicker.io)
+
+Open-sourced under the MIT License. Pull requests encouraged!
View
9 demo/filepicker_demo/models.py
@@ -1,12 +1,15 @@
from django.db import models
from django import forms
-
-import django_filepicker.models as fpmodels
+import django_filepicker
class TestModel(models.Model):
+ #Text field just to show how the FPFileField goes along with normal controls
text = models.CharField(max_length=64)
- fpfile = fpmodels.FPFileField(upload_to='uploads')
+
+ #FPFileField is a field that will render as a filepicker dragdrop widget, but
+ #When accessed will provide a File-like interface (so you can do fpfile.read(), for instance)
+ fpfile = django_filepicker.models.FPFileField(upload_to='uploads')
class TestModelForm(forms.ModelForm):
View
19 demo/filepicker_demo/views.py
@@ -4,12 +4,27 @@
def home(request):
+ message = None
if request.method == "POST":
- print request.POST, request.FILES
+ print "POST parameters: ", request.POST
+ print "Files: ", request.FILES
+
+ #building the form - automagically turns the uploaded fpurl into a File object
form = models.TestModelForm(request.POST, request.FILES)
if form.is_valid():
+ #Save will read the data and upload it to the location defined in TestModel
form.save()
+
+ #Reading the contents of the file
+ fpfile = form.cleaned_data['fpfile']
+ #Since we already read from it in save(), we'll want to seek to the beginning first
+ fpfile.seek(0)
+ print fpfile.read()
+
+ message = "Save successful. URL for %s: %s" % (fpfile.name, request.POST['fpfile'])
+
+ message = "Invalid form"
else:
form = models.TestModelForm()
- return render(request, "home.html", {'form': form})
+ return render(request, "home.html", {'form': form, 'message': message})
View
10 demo/settings.py
@@ -18,7 +18,7 @@
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'db.sql', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
@@ -27,6 +27,9 @@
}
}
+#Your Filepicker.io API key goes here. To get an api key, go to https://filepicker.io
+FILEPICKER_API_KEY = 'REPLACE_ME'
+
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
@@ -92,8 +95,6 @@
# Make this unique, and don't share it with anybody.
SECRET_KEY = 'iq0i&txhbz=yi^0zq342r%(5%a1o5v-3+idqt$m%4yj3o#*qt^'
-FILEPICKER_API_KEY = 'REPLACE_ME'
-
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
@@ -102,6 +103,7 @@
)
TEMPLATE_CONTEXT_PROCESSORS = {
+ #This context processor allows for convenient insertion of the filepicker.io javascript library
'django_filepicker.context_processors.js'
}
@@ -111,7 +113,7 @@
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
- #This middleware takes all filepicker urls and puts the data into request.FILES
+ #This optional middleware takes all filepicker urls and puts the data into request.FILES
'django_filepicker.middleware.URLFileMapperMiddleware',
)
View
24 demo/templates/home.html
@@ -1,13 +1,31 @@
<html>
<head>
{{FILEPICKER_JS}}
+ <title>Filepicker.io Django Library | Demo</title>
</head>
<body>
- <h1>Testing</h1>
+ <h1>Filepicker.io Django Library - Demo page</h1>
+ {%if message%}<p>{{message}}</p>{%endif%}
<form method="post" action="/">
{%csrf_token%}
- {{ form }}
- <input type="submit" value="Submit"/>
+ {{ form.as_p }}
+ <p><input type="submit" value="Submit"/></p>
</form>
+ <h3>Form code:</h3>
+ <pre>import django_filepicker
+
+class TestModel(models.Model):
+ text = models.CharField(max_length=64)
+ fpfile = django_filepicker.models.FPFileField(upload_to='uploads')
+</pre>
+ <h3>Processing the form</h3>
+ <pre>form = models.TestModelForm(request.POST, request.FILES)
+if form.is_valid():
+ #Save will read the data and upload it to the location defined in TestModel
+ form.save()</pre>
+
+ <hr/>
+ <p>Code available on GitHub at <a href="https://github.com/Filepicker/django-filepicker">https://github.com/Filepicker/django-filepicker</a>.</p>
+ <p>For more info and to get an api key, check out <a href="https://filepicker.io/">Filepicker.io</a>.</p>
</body>
</html>
View
2  demo/urls.py
@@ -5,6 +5,6 @@
# admin.autodiscover()
urlpatterns = patterns('',
- # Examples:
+ # The demo page:
url(r'^$', 'demo.filepicker_demo.views.home', name='home'),
)
View
5 django_filepicker/__init__.py
@@ -0,0 +1,5 @@
+import models
+import forms
+import middleware
+import widgets
+import context_processors
View
3  django_filepicker/context_processors.py
@@ -1,10 +1,11 @@
from django.utils.safestring import mark_safe
-
+#JS_URL is the url to the filepicker.io javascript library
JS_VERSION = 0
JS_URL = "//api.filepicker.io/v%d/filepicker.js" % (JS_VERSION)
def js(request):
+ #Defines a {{FILEPICKER_JS}} tag that inserts the filepicker javascript library
return {"FILEPICKER_JS":
mark_safe(u'<script src="%s"></script>' % JS_URL)}
View
33 django_filepicker/forms.py
@@ -4,8 +4,10 @@
import widgets
import urllib2
-
-#Expects FILEPICKER_API_KEY to be set in settings
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
class FPFileField(forms.FileField):
@@ -13,12 +15,25 @@ class FPFileField(forms.FileField):
default_mimetypes = "*/*"
def __init__(self, *args, **kwargs):
- self.apikey = kwargs.pop('apikey', settings.FILEPICKER_API_KEY)
- self.multiple = kwargs.pop('multiple', False)
- self.persist = kwargs.pop('persist', False)
+ """
+ Initializes the Filepicker file field.
+ Valid arguments:
+ * apikey. This string is required if it isn't set as settings.FILEPICKER_API_KEY
+ * mimetypes. Optional, the allowed mimetypes for files. Defaults to "*/*" (all files)
+ """
+
+ if 'apikey' in kwargs:
+ self.apikey = kwargs.pop('apikey')
+ elif hasattr(settings, 'FILEPICKER_API_KEY'):
+ self.apikey = settings.FILEPICKER_API_KEY
+ else:
+ raise Exception("Cannot find filepicker.io api key." +
+ " Be sure to either pass as the apikey argument when creating the FPFileField," +
+ " or set it as settings.FILEPICKER_API_KEY. To get a key, go to https://filepicker.io")
self.mimetypes = kwargs.pop('mimetypes', self.default_mimetypes)
if not isinstance(self.mimetypes, basestring):
+ #If mimetypes is an array, form a csv string
try:
self.mimetypes = ",".join(iter(self.mimetypes))
except TypeError:
@@ -32,14 +47,10 @@ def widget_attrs(self, widget):
'data-fp-mimetypes': self.mimetypes,
}
- if self.multiple:
- attrs['data-fp-multiple'] = "true"
- if self.persist:
- attrs['data-fp-persist'] = "true"
-
return attrs
def to_python(self, data):
+ """Takes the url in data and creates a File object"""
if not data:
return None
@@ -52,7 +63,7 @@ def to_python(self, data):
name = "fp-file"
size = long(url_fp.info().getheader('Content-Length', 0))
- fp = File(url_fp, name=name)
+ fp = File(StringIO(url_fp.read()), name=name)
fp.size = size
return fp
View
21 django_filepicker/middleware.py
@@ -2,6 +2,11 @@
import urllib2
from django.core.files import File
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
class URLFileMapperMiddleware(object):
"""
@@ -22,14 +27,14 @@ def process_request(self, request):
#Iterate over GET or POST data, search for filepicker.io urls
for key, val in request.POST.items():
if self.isFilepickerURL(val):
- url_fp = urllib2.urlopen(val)
- disposition = url_fp.info().getheader('Content-Disposition')
- if disposition:
- name = disposition.rpartition("filename=")[2].strip('" ')
- else:
- name = "fp-file"
-
- request.FILES[key] = File(val, name=name)
+ url_fp = urllib2.urlopen(val)
+ disposition = url_fp.info().getheader('Content-Disposition')
+ if disposition:
+ name = disposition.rpartition("filename=")[2].strip('" ')
+ else:
+ name = "fp-file"
+
+ request.FILES[key] = File(StringIO(url_fp.read()), name=name)
def isFilepickerURL(self, val):
return bool(self.filepicker_url_regex.match(val))
View
17 django_filepicker/models.py
@@ -7,6 +7,18 @@
class FPFileField(models.FileField):
description = ugettext_lazy("A File selected using Filepicker.io")
+ def __init__(self, *args, **kwargs):
+ """
+ Initializes the Filepicker file field.
+ Valid arguments:
+ * apikey. This string is required if it isn't set as settings.FILEPICKER_API_KEY
+ * mimetypes. Optional, the allowed mimetypes for files. Defaults to "*/*" (all files)
+ """
+ self.apikey = kwargs.pop("apikey", None)
+ self.mimetypes = kwargs.pop("mimetypes", None)
+
+ super(FPFileField, self).__init__(*args, **kwargs)
+
def formfield(self, **kwargs):
defaults = {'form_class': forms.FPFileField,
'max_length': self.max_length}
@@ -14,5 +26,10 @@ def formfield(self, **kwargs):
if 'initial' in kwargs:
defaults['required'] = False
+ if self.apikey:
+ defaults['apikey'] = self.apikey
+ if self.mimetypes:
+ defaults['mimetypes'] = self.mimetypes
+
defaults.update(kwargs)
return super(FPFileField, self).formfield(**defaults)
Please sign in to comment.
Something went wrong with that request. Please try again.