Commit 4457ba00 authored by Jacob Kaplan-Moss's avatar Jacob Kaplan-Moss
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
parent bc1f67a6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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>
+10 −0
Original line number Diff line number Diff line
@@ -843,6 +843,16 @@ class FilePathField(Field):
        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)]

+29 −1
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ Field classes.

import copy
import datetime
import os
import re
import time
# Python 2.3 fallbacks
@@ -31,7 +32,7 @@ __all__ = (
    '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 @@ class MultiValueField(Field):
        """
        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.'),
+37 −4
Original line number Diff line number Diff line
@@ -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``
~~~~~~~~~~~~~~

+27 −0
Original line number Diff line number Diff line
@@ -1133,6 +1133,33 @@ u''
>>> 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()