Ticket #5893: allow_folders.5.diff
File allow_folders.5.diff, 11.8 KB (added by , 16 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): 493 493 curry(cls._get_next_or_previous_by_FIELD, field=self, is_next=False)) 494 494 495 495 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 497 497 # to a string so the database backend always sees a consistent type. 498 498 if lookup_type in ('month', 'day', 'week_day'): 499 499 return [force_unicode(value)] … … class EmailField(CharField): 637 637 return super(EmailField, self).formfield(**defaults) 638 638 639 639 class 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): 641 642 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 642 645 kwargs['max_length'] = kwargs.get('max_length', 100) 643 646 Field.__init__(self, verbose_name, name, **kwargs) 644 647 … … class FilePathField(Field): 648 651 'match': self.match, 649 652 'recursive': self.recursive, 650 653 'form_class': forms.FilePathField, 654 'allow_files': self.allow_files, 655 'allow_folders': self.allow_folders, 651 656 } 652 657 defaults.update(kwargs) 653 658 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): 256 256 digits = len(digittuple) 257 257 if decimals > digits: 258 258 # 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 261 261 # we would not allow max_digits = decimal_places. 262 262 digits = decimals 263 263 whole_digits = digits - decimals … … DEFAULT_DATE_INPUT_FORMATS = ( 283 283 ) 284 284 285 285 class DateField(Field): 286 widget = DateInput 286 widget = DateInput 287 287 default_error_messages = { 288 288 'invalid': _(u'Enter a valid date.'), 289 289 } … … class MultiValueField(Field): 822 822 raise NotImplementedError('Subclasses must implement this method.') 823 823 824 824 class FilePathField(ChoiceField): 825 def __init__(self, path, match=None, recursive=False, required=True,826 widget=None, label=None, initial=None, help_text=None,827 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): 828 828 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 829 831 super(FilePathField, self).__init__(choices=(), required=required, 830 832 widget=widget, label=label, initial=initial, help_text=help_text, 831 833 *args, **kwargs) 832 834 833 835 if self.required: 834 836 self.choices = [] 835 837 else: … … class FilePathField(ChoiceField): 840 842 841 843 if recursive: 842 844 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))) 847 855 else: 848 856 try: 849 857 for f in os.listdir(self.path): 850 858 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))): 852 862 self.choices.append((full_file, f)) 853 863 except OSError: 854 864 pass -
docs/ref/forms/fields.txt
diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt index 63ac707..a3e12b6 100644
a b Takes one extra required argument: 328 328 329 329 An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this 330 330 field. 331 331 332 332 ``TypedChoiceField`` 333 333 ~~~~~~~~~~~~~~~~~~~~ 334 334 … … If no ``input_formats`` argument is provided, the default input formats are:: 437 437 ``min_value``, ``max_digits``, ``max_decimal_places``, 438 438 ``max_whole_digits`` 439 439 440 Takes four optional arguments: 440 Takes four optional arguments: 441 441 442 442 .. attribute:: DecimalField.max_value 443 443 .. attribute:: DecimalField.min_value … … Takes four optional arguments: 449 449 The maximum number of digits (those before the decimal point plus those 450 450 after the decimal point, with leading zeros stripped) permitted in the 451 451 value. 452 452 453 453 .. attribute:: DecimalField.decimal_places 454 454 455 455 The maximum number of decimal places permitted. … … extra arguments; only ``path`` is required: 522 522 A regular expression pattern; only files with names matching this expression 523 523 will be allowed as choices. 524 524 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 548 Takes two optional arguments for validation, ``max_value`` and ``min_value``. 537 549 These control the range of values permitted in the field. 538 550 539 551 ``ImageField`` … … example:: 779 791 (which is ``"---------"`` by default) with the ``empty_label`` attribute, or 780 792 you can disable the empty label entirely by setting ``empty_label`` to 781 793 ``None``:: 782 794 783 795 # A custom empty label 784 796 field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)") 785 797 786 798 # No empty label 787 799 field2 = forms.ModelChoiceField(queryset=..., empty_label=None) 788 800 -
docs/ref/models/fields.txt
diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index 6630b7b..24562bd 100644
a b directory on the filesystem. Has three special arguments, of which the first is 571 571 Optional. Either ``True`` or ``False``. Default is ``False``. Specifies 572 572 whether all subdirectories of :attr:`~FilePathField.path` should be included 573 573 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 574 587 Of course, these arguments can be used together. 575 588 576 589 The 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 1104 1104 1105 1105 # TypedChoiceField ############################################################ 1106 1106 1107 # TypedChoiceField is just like ChoiceField, except that coerced types will 1107 # TypedChoiceField is just like ChoiceField, except that coerced types will 1108 1108 # be returned: 1109 1109 >>> f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int) 1110 1110 >>> f.clean('1') … … ValidationError: [u'Select a valid choice. 2 is not one of the available choices 1122 1122 1123 1123 # This can also cause weirdness: be careful (bool(-1) == True, remember) 1124 1124 >>> f.coerce = bool 1125 >>> f.clean('-1') 1125 >>> f.clean('-1') 1126 1126 True 1127 1127 1128 1128 # Even more weirdness: if you have a valid choice but your coercion function … … u'.../django/forms/fields.py' 1344 1344 >>> fix_os_paths(f.choices) 1345 1345 [('.../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')] 1346 1346 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 1347 1355 # SplitDateTimeField ########################################################## 1348 1356 1349 1357 >>> f = SplitDateTimeField()