Ticket #5893: allow_folders.4.diff

File allow_folders.4.diff, 11.8 KB (added by Alex Gaynor, 15 years ago)
  • django/db/models/fields/__init__.py

    diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
    index bc41911..3f70a37 100644
    a b class DateField(Field):  
    493493                curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False))
    494494
    495495    def get_db_prep_lookup(self, lookup_type, value):
    496         # For "__month", "__day", and "__week_day" lookups, convert the value 
     496        # For "__month", "__day", and "__week_day" lookups, convert the value
    497497        # to a string so the database backend always sees a consistent type.
    498498        if lookup_type in ('month', 'day', 'week_day'):
    499499            return [force_unicode(value)]
    class EmailField(CharField):  
    637637        return super(EmailField, self).formfield(**defaults)
    638638
    639639class FilePathField(Field):
    640     def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
     640    def __init__(self, verbose_name=None, name=None, path='', match=None,
     641        recursive=False, allow_files=True, allow_folders=False, **kwargs):
    641642        self.path, self.match, self.recursive = path, match, recursive
     643        self.allow_files, self.allow_folders =  allow_files, allow_folders
     644        assert self.allow_files or self.allow_folders
    642645        kwargs['max_length'] = kwargs.get('max_length', 100)
    643646        Field.__init__(self, verbose_name, name, **kwargs)
    644647
    class FilePathField(Field):  
    648651            'match': self.match,
    649652            'recursive': self.recursive,
    650653            'form_class': forms.FilePathField,
     654            'allow_files': self.allow_files,
     655            'allow_folders': self.allow_folders,
    651656        }
    652657        defaults.update(kwargs)
    653658        return super(FilePathField, self).formfield(**defaults)
  • django/forms/fields.py

    diff --git a/django/forms/fields.py b/django/forms/fields.py
    index bd4f3d4..a84c327 100644
    a b class DecimalField(Field):  
    256256        digits = len(digittuple)
    257257        if decimals > digits:
    258258            # We have leading zeros up to or past the decimal point.  Count
    259             # everything past the decimal point as a digit.  We do not count 
    260             # 0 before the decimal point as a digit since that would mean 
     259            # everything past the decimal point as a digit.  We do not count
     260            # 0 before the decimal point as a digit since that would mean
    261261            # we would not allow max_digits = decimal_places.
    262262            digits = decimals
    263263        whole_digits = digits - decimals
    DEFAULT_DATE_INPUT_FORMATS = (  
    283283)
    284284
    285285class DateField(Field):
    286     widget = DateInput 
     286    widget = DateInput
    287287    default_error_messages = {
    288288        'invalid': _(u'Enter a valid date.'),
    289289    }
    class MultiValueField(Field):  
    822822        raise NotImplementedError('Subclasses must implement this method.')
    823823
    824824class 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):
     825    def __init__(self, path, match=None, recursive=False, allow_files=True,
     826        allow_folders=False, required=True, widget=Select, label=None,
     827        initial=None, help_text=None, *args, **kwargs):
    828828        self.path, self.match, self.recursive = path, match, recursive
     829        self.allow_files, self.allow_folders = allow_files, allow_folders
     830        assert self.allow_files or self.allow_folders
    829831        super(FilePathField, self).__init__(choices=(), required=required,
    830832            widget=widget, label=label, initial=initial, help_text=help_text,
    831833            *args, **kwargs)
    832            
     834
    833835        if self.required:
    834836            self.choices = []
    835837        else:
    class FilePathField(ChoiceField):  
    840842
    841843        if recursive:
    842844            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)))
     845                if self.allow_files:
     846                    for f in files:
     847                        if self.match is None or self.match_re.search(f):
     848                            f = os.path.join(root, f)
     849                            self.choices.append((f, f.replace(path, "", 1)))
     850                if self.allow_folders:
     851                    for f in dirs:
     852                        if self.match is None or self.match_re.search(f):
     853                            f = os.path.join(root, f)
     854                            self.choices.append((f, f.replace(path, "", 1)))
    847855        else:
    848856            try:
    849857                for f in os.listdir(self.path):
    850858                    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)):
     859                    if (((self.allow_files and os.path.isfile(full_file)) or
     860                        (self.allow_folders and os.path.isdir(full_file))) and
     861                        (self.match is None or self.match_re.search(f))):
    852862                        self.choices.append((full_file, f))
    853863            except OSError:
    854864                pass
  • docs/ref/forms/fields.txt

    diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
    index 63ac707..47bbb1f 100644
    a b Takes one extra required argument:  
    328328
    329329    An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this
    330330    field.
    331    
     331
    332332``TypedChoiceField``
    333333~~~~~~~~~~~~~~~~~~~~
    334334
    If no ``input_formats`` argument is provided, the default input formats are::  
    437437      ``min_value``, ``max_digits``, ``max_decimal_places``,
    438438      ``max_whole_digits``
    439439
    440 Takes four optional arguments: 
     440Takes four optional arguments:
    441441
    442442.. attribute:: DecimalField.max_value
    443443.. attribute:: DecimalField.min_value
    Takes four optional arguments:  
    449449    The maximum number of digits (those before the decimal point plus those
    450450    after the decimal point, with leading zeros stripped) permitted in the
    451451    value.
    452    
     452
    453453.. attribute:: DecimalField.decimal_places
    454454
    455455    The maximum number of decimal places permitted.
    extra arguments; only ``path`` is required:  
    522522    A regular expression pattern; only files with names matching this expression
    523523    will be allowed as choices.
    524524
    525 ``FloatField``
    526 ~~~~~~~~~~~~~~
    527 
    528     * Default widget: ``TextInput``
    529     * Empty value: ``None``
    530     * Normalizes to: A Python float.
    531     * Validates that the given value is an float. Leading and trailing
    532       whitespace is allowed, as in Python's ``float()`` function.
    533     * Error message keys: ``required``, ``invalid``, ``max_value``,
    534       ``min_value``
    535          
    536 Takes two optional arguments for validation, ``max_value`` and ``min_value``.
     525.. attribute:: FilePathField.allow_files
     526
     527    Optional.  Either ``True`` or ``False``.  Default is ``True``.  Specifies
     528    whether files in the specified location should be included.  Either this or
     529    :attr:`~FilePathField.allow_folders` must be ``True.
     530
     531.. attribute:: FilePathField.allow_folders
     532
     533    Optional.  Either ``True`` or ``False``.  Default is ``False``.  Specifies
     534    whether folders in the specified location should be included.  Either this
     535    or :attr:`~FilePathField.allow_files` must be ``True.
     536
     537``FloatField``
     538~~~~~~~~~~~~~~
     539
     540    * Default widget: ``TextInput``
     541    * Empty value: ``None``
     542    * Normalizes to: A Python float.
     543    * Validates that the given value is an float. Leading and trailing
     544      whitespace is allowed, as in Python's ``float()`` function.
     545    * Error message keys: ``required``, ``invalid``, ``max_value``,
     546      ``min_value``
     547
     548Takes two optional arguments for validation, ``max_value`` and ``min_value``.
    537549These control the range of values permitted in the field.
    538550
    539551``ImageField``
    example::  
    779791   (which is ``"---------"`` by default) with the ``empty_label`` attribute, or
    780792   you can disable the empty label entirely by setting ``empty_label`` to
    781793   ``None``::
    782    
     794
    783795        # A custom empty label
    784796        field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)")
    785        
     797
    786798        # No empty label
    787799        field2 = forms.ModelChoiceField(queryset=..., empty_label=None)
    788800
  • docs/ref/models/fields.txt

    diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
    index 6630b7b..f0ff39b 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    Optional.  Either ``True`` or ``False``.  Default is ``True``.  Specifies
     577    whether files in the specified location should be included.  Either this or
     578    :attr:`~FilePathField.allow_folders` must be ``True.
     579
     580.. attribute:: FilePathField.allow_folders
     581
     582    Optional.  Either ``True`` or ``False``.  Default is ``False``.  Specifies
     583    whether folders in the specified location should be included.  Either this
     584    or :attr:`~FilePathField.allow_files` must be ``True.
     585
     586
    574587Of course, these arguments can be used together.
    575588
    576589The 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 0dc49f2..4b218bf 100644
    a b ValidationError: [u'Select a valid choice. 6 is not one of the available choices  
    11041104
    11051105# TypedChoiceField ############################################################
    11061106
    1107 # TypedChoiceField is just like ChoiceField, except that coerced types will 
     1107# TypedChoiceField is just like ChoiceField, except that coerced types will
    11081108# be returned:
    11091109>>> f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int)
    11101110>>> f.clean('1')
    ValidationError: [u'Select a valid choice. 2 is not one of the available choices  
    11221122
    11231123# This can also cause weirdness: be careful (bool(-1) == True, remember)
    11241124>>> f.coerce = bool
    1125 >>> f.clean('-1') 
     1125>>> f.clean('-1')
    11261126True
    11271127
    11281128# Even more weirdness: if you have a valid choice but your coercion function
    u'.../django/forms/fields.py'  
    13441344>>> fix_os_paths(f.choices)
    13451345[('.../django/forms/__init__.py', '__init__.py'), ('.../django/forms/extras/__init__.py', 'extras/__init__.py'), ('.../django/forms/extras/widgets.py', 'extras/widgets.py'), ('.../django/forms/fields.py', 'fields.py'), ('.../django/forms/forms.py', 'forms.py'), ('.../django/forms/models.py', 'models.py'), ('.../django/forms/util.py', 'util.py'), ('.../django/forms/widgets.py', 'widgets.py')]
    13461346
     1347>>> f = forms.FilePathField(path=path, allow_folders=True, allow_files=False)
     1348>>> fix_os_paths(f.choices)
     1349[('.../django/forms/extras', 'extras')]
     1350>>> f = forms.FilePathField(path=path, allow_folders=True, allow_files=True)
     1351>>> f.choices.sort()
     1352>>> fix_os_paths(f.choices)
     1353[('.../django/forms/__init__.py', '__init__.py'), ('.../django/forms/__init__.pyc', '__init__.pyc'), ('.../django/forms/extras', 'extras'), ('.../django/forms/fields.py', 'fields.py'), ('.../django/forms/fields.pyc', 'fields.pyc'), ('.../django/forms/forms.py', 'forms.py'), ('.../django/forms/forms.pyc', 'forms.pyc'), ('.../django/forms/formsets.pyc', 'formsets.pyc'), ('.../django/forms/models.py', 'models.py'), ('.../django/forms/models.pyc', 'models.pyc'), ('.../django/forms/util.py', 'util.py'), ('.../django/forms/util.pyc', 'util.pyc'), ('.../django/forms/widgets.py', 'widgets.py'), ('.../django/forms/widgets.pyc', 'widgets.pyc')]
     1354
    13471355# SplitDateTimeField ##########################################################
    13481356
    13491357>>> f = SplitDateTimeField()
Back to Top