Ticket #5893: filepath-folders.2.diff

File filepath-folders.2.diff, 10.3 KB (added by Alex Gaynor, 14 years ago)

Resolves issues.

  • django/core/management/validation.py

    diff --git a/django/core/management/validation.py b/django/core/management/validation.py
    index 97164d7..185edd1 100644
    a b def get_validation_errors(outfile, app=None):  
    5353                    e.add(opts, '"%s": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
    5454            if isinstance(f, models.BooleanField) and getattr(f, 'null', False):
    5555                e.add(opts, '"%s": BooleanFields do not accept null values. Use a NullBooleanField instead.' % f.name)
     56            if isinstance(f, models.FilePathField) and not (f.allow_files or f.allow_folders):
     57                e.add(opts, '"%s": FilePathFields must have either allow_files or allow_folders set to True.' % f.name)
    5658            if f.choices:
    5759                if isinstance(f.choices, basestring) or not is_iterable(f.choices):
    5860                    e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name)
  • django/db/models/fields/__init__.py

    diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
    index 05238cf..95cf61a 100644
    a b  
    11import copy
    22import datetime
     3import decimal
    34import os
    45import re
    56import time
    6 try:
    7     import decimal
    8 except ImportError:
    9     from django.utils import _decimal as decimal    # for Python 2.3
    107
    118from django.db import connection
    129from django.db.models import signals
    class EmailField(CharField):  
    671668class FilePathField(Field):
    672669    """File path"""
    673670   
    674     def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
     671    def __init__(self, verbose_name=None, name=None, path='', match=None,
     672        recursive=False, allow_files=True, allow_folders=False, **kwargs):
    675673        self.path, self.match, self.recursive = path, match, recursive
     674        self.allow_files, self.allow_folders =  allow_files, allow_folders
    676675        kwargs['max_length'] = kwargs.get('max_length', 100)
    677676        Field.__init__(self, verbose_name, name, **kwargs)
    678677
    class FilePathField(Field):  
    682681            'match': self.match,
    683682            'recursive': self.recursive,
    684683            'form_class': forms.FilePathField,
     684            'allow_files': self.allow_files,
     685            'allow_folders': self.allow_folders,
    685686        }
    686687        defaults.update(kwargs)
    687688        return super(FilePathField, self).formfield(**defaults)
  • django/forms/fields.py

    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index 0aef355..db6ebd0 100644
    a b try:  
    1212    from cStringIO import StringIO
    1313except ImportError:
    1414    from StringIO import StringIO
     15from decimal import Decimal, DecimalException
    1516
    16 # Python 2.3 fallbacks
    17 try:
    18     from decimal import Decimal, DecimalException
    19 except ImportError:
    20     from django.utils._decimal import Decimal, DecimalException
    21 try:
    22     set
    23 except NameError:
    24     from sets import Set as set
    2517
    2618import django.core.exceptions
    2719from django.utils.translation import ugettext_lazy as _
    class MultiValueField(Field):  
    822814        raise NotImplementedError('Subclasses must implement this method.')
    823815
    824816class FilePathField(ChoiceField):
    825     def __init__(self, path, match=None, recursive=False, required=True,
    826                  widget=None, label=None, initial=None, help_text=None,
    827                 *args, **kwargs):
     817    def __init__(self, path, match=None, recursive=False, allow_files=True,
     818        allow_folders=False, required=True, widget=Select, label=None,
     819        initial=None, help_text=None, *args, **kwargs):
    828820        self.path, self.match, self.recursive = path, match, recursive
     821        self.allow_files, self.allow_folders = allow_files, allow_folders
    829822        super(FilePathField, self).__init__(choices=(), required=required,
    830823            widget=widget, label=label, initial=initial, help_text=help_text,
    831824            *args, **kwargs)
    class FilePathField(ChoiceField):  
    840833
    841834        if recursive:
    842835            for root, dirs, files in os.walk(self.path):
    843                 for f in files:
    844                     if self.match is None or self.match_re.search(f):
    845                         f = os.path.join(root, f)
    846                         self.choices.append((f, f.replace(path, "", 1)))
     836                if self.allow_files:
     837                    for f in files:
     838                        if self.match is None or self.match_re.search(f):
     839                            f = os.path.join(root, f)
     840                            self.choices.append((f, f.replace(path, "", 1)))
     841                if self.allow_folders:
     842                    for f in dirs:
     843                        if self.match is None or self.match_re.search(f):
     844                            f = os.path.join(root, f)
     845                            self.choices.append((f, f.replace(path, "", 1)))
    847846        else:
    848847            try:
    849848                for f in os.listdir(self.path):
    850849                    full_file = os.path.join(self.path, f)
    851                     if os.path.isfile(full_file) and (self.match is None or self.match_re.search(f)):
     850                    if (((self.allow_files and os.path.isfile(full_file)) or
     851                        (self.allow_folders and os.path.isdir(full_file))) and
     852                        (self.match is None or self.match_re.search(f))):
    852853                        self.choices.append((full_file, f))
    853854            except OSError:
    854855                pass
  • docs/ref/forms/fields.txt

    diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
    index 4bb6a7c..74be0c6 100644
    a b extra arguments; only ``path`` is required:  
    523523    A regular expression pattern; only files with names matching this expression
    524524    will be allowed as choices.
    525525
     526.. attribute:: FilePathField.allow_files
     527
     528    .. versionadded:: 1.2
     529
     530    Optional.  Either ``True`` or ``False``.  Default is ``True``.  Specifies
     531    whether files in the specified location should be included.  Either this or
     532    :attr:`~FilePathField.allow_folders` must be ``True``.
     533
     534.. attribute:: FilePathField.allow_folders
     535
     536    .. versionadded:: 1.2
     537
     538    Optional.  Either ``True`` or ``False``.  Default is ``False``.  Specifies
     539    whether folders in the specified location should be included.  Either this
     540    or :attr:`~FilePathField.allow_files` must be ``True``.
     541
    526542``FloatField``
    527543~~~~~~~~~~~~~~
    528544
  • docs/ref/models/fields.txt

    diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
    index 0cb5be4..fba9e07 100644
    a b directory on the filesystem. Has three special arguments, of which the first is  
    571571    Optional. Either ``True`` or ``False``. Default is ``False``. Specifies
    572572    whether all subdirectories of :attr:`~FilePathField.path` should be included
    573573
     574.. attribute:: FilePathField.allow_files
     575
     576    .. versionadded:: 1.2
     577
     578    Optional.  Either ``True`` or ``False``.  Default is ``True``.  Specifies
     579    whether files in the specified location should be included.  Either this or
     580    :attr:`~FilePathField.allow_folders` must be ``True``.
     581
     582.. attribute:: FilePathField.allow_folders
     583
     584    .. versionadded:: 1.2
     585
     586    Optional.  Either ``True`` or ``False``.  Default is ``False``.  Specifies
     587    whether folders in the specified location should be included.  Either this
     588    or :attr:`~FilePathField.allow_files` must be ``True``.
     589
     590
    574591Of course, these arguments can be used together.
    575592
    576593The one potential gotcha is that :attr:`~FilePathField.match` applies to the
  • tests/regressiontests/forms/fields.py

    diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py
    index c9736d3..c67e68f 100644
    a b Each Field's __init__() takes at least these parameters:  
    2424Other than that, the Field subclasses have class-specific options for
    2525__init__(). For example, CharField has a max_length option.
    2626"""
     27
    2728import datetime
    2829import time
    2930import re
    3031import os
    3132
     33from decimal import Decimal
    3234from unittest import TestCase
    3335
    3436from django.core.files.uploadedfile import SimpleUploadedFile
    3537from django.forms import *
    3638from django.forms.widgets import RadioFieldRenderer
    3739
    38 try:
    39     from decimal import Decimal
    40 except ImportError:
    41     from django.utils._decimal import Decimal
    42 
    4340
    4441def fix_os_paths(x):
    4542    if isinstance(x, basestring):
    class FieldsTests(TestCase):  
    815812        for exp, got in zip(expected, fix_os_paths(f.choices)):
    816813            self.assertEqual(exp[1], got[1])
    817814            assert got[0].endswith(exp[0])
     815   
     816    def test_filepathfield_folders(self):
     817        path = forms.__file__
     818        path = os.path.dirname(path) + '/'
     819        f = FilePathField(path=path, allow_folders=True, allow_files=False)
     820        f.choices.sort()
     821        expected = [
     822            ('/django/forms/extras', 'extras'),
     823        ]
     824        for exp, got in zip(expected, fix_os_paths(f.choices)):
     825            self.assertEqual(exp[1], got[1])
     826            self.assert_(got[0].endswith(exp[0]))
     827       
     828        f = FilePathField(path=path, allow_folders=True, allow_files=True)
     829        f.choices.sort()
     830        expected = [
     831            ('/django/forms/__init__.py', '__init__.py'),
     832            ('/django/forms/__init__.pyc', '__init__.pyc'),
     833            ('/django/forms/extras', 'extras'),
     834            ('/django/forms/fields.py', 'fields.py'),
     835            ('/django/forms/fields.pyc', 'fields.pyc'),
     836            ('/django/forms/forms.py', 'forms.py'),
     837            ('/django/forms/forms.pyc', 'forms.pyc'),
     838            ('/django/forms/formsets.py', 'formsets.py'),
     839            ('/django/forms/formsets.pyc', 'formsets.pyc'),
     840            ('/django/forms/models.py', 'models.py'),
     841            ('/django/forms/models.pyc', 'models.pyc'),
     842            ('/django/forms/util.py', 'util.py'),
     843            ('/django/forms/util.pyc', 'util.pyc'),
     844            ('/django/forms/widgets.py', 'widgets.py'),
     845            ('/django/forms/widgets.pyc', 'widgets.pyc')
     846        ]
     847        for exp, got in zip(expected, fix_os_paths(f.choices)):
     848            self.assertEqual(exp[1], got[1])
     849            self.assert_(got[0].endswith(exp[0]))
     850
    818851
    819852    # SplitDateTimeField ##########################################################
    820853
Back to Top