Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #5894: added FilePathField to newforms. Thanks, Alex Gaynor.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@7323 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 4457ba002d64d4a991b0561c5be69a8c61b2b828 1 parent bc1f67a
@jacobian jacobian authored
View
1  AUTHORS
@@ -146,6 +146,7 @@ answer newbie questions, and generally made Django that much better:
Jorge Gajon <gajon@gajon.org>
gandalf@owca.info
Marc Garcia <marc.garcia@accopensys.com>
+ Alex Gaynor <alex.gaynor@gmail.com>
Andy Gayton <andy-django@thecablelounge.com>
Baishampayan Ghose
Dimitris Glezos <dimitris@glezos.com>
View
10 django/db/models/fields/__init__.py
@@ -842,6 +842,16 @@ def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=
self.path, self.match, self.recursive = path, match, recursive
kwargs['max_length'] = kwargs.get('max_length', 100)
Field.__init__(self, verbose_name, name, **kwargs)
+
+ def formfield(self, **kwargs):
+ defaults = {
+ 'path': self.path,
+ 'match': self.match,
+ 'recursive': self.recursive,
+ 'form_class': forms.FilePathField,
+ }
+ defaults.update(kwargs)
+ return super(FilePathField, self).formfield(**defaults)
def get_manipulator_field_objs(self):
return [curry(oldforms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)]
View
30 django/newforms/fields.py
@@ -4,6 +4,7 @@
import copy
import datetime
+import os
import re
import time
# Python 2.3 fallbacks
@@ -31,7 +32,7 @@
'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
- 'SplitDateTimeField', 'IPAddressField',
+ 'SplitDateTimeField', 'IPAddressField', 'FilePathField',
)
# These values, if given to to_python(), will trigger the self.required check.
@@ -718,6 +719,33 @@ def compress(self, data_list):
"""
raise NotImplementedError('Subclasses must implement this method.')
+class FilePathField(ChoiceField):
+ def __init__(self, path, match=None, recursive=False, required=True,
+ widget=Select, label=None, initial=None, help_text=None,
+ *args, **kwargs):
+ self.path, self.match, self.recursive = path, match, recursive
+ super(FilePathField, self).__init__(choices=(), required=required,
+ widget=widget, label=label, initial=initial, help_text=help_text,
+ *args, **kwargs)
+ self.choices = []
+ if self.match is not None:
+ self.match_re = re.compile(self.match)
+ if recursive:
+ for root, dirs, files in os.walk(self.path):
+ for f in files:
+ if self.match is None or self.match_re.search(f):
+ f = os.path.join(root, f)
+ self.choices.append((f, f.replace(path, "", 1)))
+ else:
+ try:
+ for f in os.listdir(self.path):
+ full_file = os.path.join(self.path, f)
+ if os.path.isfile(full_file) and (self.match is None or self.match_re.search(f)):
+ self.choices.append((full_file, f))
+ except OSError:
+ pass
+ self.widget.choices = self.choices
+
class SplitDateTimeField(MultiValueField):
default_error_messages = {
'invalid_date': _(u'Enter a valid date.'),
View
41 docs/newforms.txt
@@ -1333,13 +1333,14 @@ given length.
An ``UploadedFile`` object has two attributes:
- ====================== =====================================================
- Argument Description
- ====================== =====================================================
+ ====================== ====================================================
+ Attribute Description
+ ====================== ====================================================
``filename`` The name of the file, provided by the uploading
client.
+
``content`` The array of bytes comprising the file content.
- ====================== =====================================================
+ ====================== ====================================================
The string representation of an ``UploadedFile`` is the same as the filename
attribute.
@@ -1349,6 +1350,38 @@ When you use a ``FileField`` on a form, you must also remember to
.. _`bind the file data to the form`: `Binding uploaded files to a form`_
+``FilePathField``
+~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+ * Default widget: ``Select``
+ * Empty value: ``None``
+ * Normalizes to: A unicode object
+ * Validates that the selected choice exists in the list of choices.
+ * Error message keys: ``required``, ``invalid_choice``
+
+The field allows choosing from files inside a certain directory. It takes three
+extra arguments:
+
+ ============== ========== ===============================================
+ Argument Required? Description
+ ============== ========== ===============================================
+ ``path`` Yes The absolute path to the directory whose
+ contents you want listed. This directory must
+ exist.
+
+ ``recursive`` No If ``False`` (the default) only the direct
+ contents of ``path`` will be offered as choices.
+ If ``True``, the directory will be descended
+ into recursively and all descendants will be
+ listed as choices.
+
+ ``match`` No A regular expression pattern; only files with
+ names matching this expression will be allowed
+ as choices.
+ ============== ========== ===============================================
+
``ImageField``
~~~~~~~~~~~~~~
View
27 tests/regressiontests/forms/fields.py
@@ -1133,6 +1133,33 @@
>>> f.clean(None)
u''
+# FilePathField ###############################################################
+
+>>> import os
+>>> from django import newforms as forms
+>>> path = forms.__file__
+>>> path = os.path.dirname(path) + '/'
+>>> path
+'.../django/newforms/'
+>>> f = forms.FilePathField(path=path)
+>>> f.choices.sort()
+>>> f.choices
+[('.../django/newforms/__init__.py', '__init__.py'), ('.../django/newforms/__init__.pyc', '__init__.pyc'), ('.../django/newforms/fields.py', 'fields.py'), ('.../django/newforms/fields.pyc', 'fields.pyc'), ('.../django/newforms/forms.py', 'forms.py'), ('.../django/newforms/forms.pyc', 'forms.pyc'), ('.../django/newforms/models.py', 'models.py'), ('.../django/newforms/models.pyc', 'models.pyc'), ('.../django/newforms/util.py', 'util.py'), ('.../django/newforms/util.pyc', 'util.pyc'), ('.../django/newforms/widgets.py', 'widgets.py'), ('.../django/newforms/widgets.pyc', 'widgets.pyc')]
+>>> f.clean('fields.py')
+Traceback (most recent call last):
+...
+ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
+>>> f.clean(path + 'fields.py')
+u'.../django/newforms/fields.py'
+>>> f = forms.FilePathField(path=path, match='^.*?\.py$')
+>>> f.choices.sort()
+>>> f.choices
+[('.../django/newforms/__init__.py', '__init__.py'), ('.../django/newforms/fields.py', 'fields.py'), ('.../django/newforms/forms.py', 'forms.py'), ('.../django/newforms/models.py', 'models.py'), ('.../django/newforms/util.py', 'util.py'), ('.../django/newforms/widgets.py', 'widgets.py')]
+>>> f = forms.FilePathField(path=path, recursive=True, match='^.*?\.py$')
+>>> f.choices.sort()
+>>> f.choices
+[('.../django/newforms/__init__.py', '__init__.py'), ('.../django/newforms/extras/__init__.py', 'extras/__init__.py'), ('.../django/newforms/extras/widgets.py', 'extras/widgets.py'), ('.../django/newforms/fields.py', 'fields.py'), ('.../django/newforms/forms.py', 'forms.py'), ('.../django/newforms/models.py', 'models.py'), ('.../django/newforms/util.py', 'util.py'), ('.../django/newforms/widgets.py', 'widgets.py')]
+
# SplitDateTimeField ##########################################################
>>> f = SplitDateTimeField()
Please sign in to comment.
Something went wrong with that request. Please try again.