Django

Code

Changeset 378

Show
Ignore:
Timestamp:
08/01/05 16:29:52 (3 years ago)
Author:
adrian
Message:

Refactored meta.py -- created a django.core.meta package, with init.py and fields.py

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/core/management.py

    r330 r378  
    265265def get_admin_index(mod): 
    266266    "Returns admin-index template snippet (in list form) for the given module." 
    267     from django.core import meta 
     267    from django.utils.text import capfirst 
    268268    output = [] 
    269269    app_label = mod._MODELS[0]._meta.app_label 
     
    275275                'app': app_label, 
    276276                'mod': klass._meta.module_name, 
    277                 'name': meta.capfirst(klass._meta.verbose_name_plural), 
     277                'name': capfirst(klass._meta.verbose_name_plural), 
    278278                'addperm': klass._meta.get_add_permission(), 
    279279                'changeperm': klass._meta.get_change_permission(), 
  • django/trunk/django/core/meta/__init__.py

    r360 r378  
     1from django.conf import settings 
    12from django.core import formfields, validators 
    23from django.core import db 
    34from django.core.exceptions import ObjectDoesNotExist 
    4 from django.conf import settings 
     5from django.core.meta.fields import * 
     6from django.utils.functional import curry 
     7from django.utils.text import capfirst 
    58import copy, datetime, os, re, sys, types 
    6  
    7 # The values to use for "blank" in SelectFields. Will be appended to the start of most "choices" lists. 
    8 BLANK_CHOICE_DASH = [("", "---------")] 
    9 BLANK_CHOICE_NONE = [("", "None")] 
    109 
    1110# Admin stages. 
    1211ADD, CHANGE, BOTH = 1, 2, 3 
    13  
    14 # Values for Relation.edit_inline_type. 
    15 TABULAR, STACKED = 1, 2 
    16  
    17 # Values for filter_interface. 
    18 HORIZONTAL, VERTICAL = 1, 2 
    19  
    20 # Random entropy string used by "default" param. 
    21 NOT_PROVIDED = 'oijpwojefiojpanv' 
    2212 
    2313# Size of each "chunk" for get_iterator calls. 
     
    2515GET_ITERATOR_CHUNK_SIZE = 100 
    2616 
    27 # Prefix (in python path style) to location of models. 
     17# Prefix (in Python path style) to location of models. 
    2818MODEL_PREFIX = 'django.models' 
    2919 
     
    3828LOOKUP_SEPARATOR = '__' 
    3929 
    40 RECURSIVE_RELATIONSHIP_CONSTANT = 'self' 
    41  
    4230#################### 
    4331# HELPER FUNCTIONS # 
    4432#################### 
    45  
    46 # capitalizes first letter of string 
    47 capfirst = lambda x: x and x[0].upper() + x[1:] 
    48  
    49 # prepares a value for use in a LIKE query 
    50 prep_for_like_query = lambda x: str(x).replace("%", "\%").replace("_", "\_") 
    51  
    52 # returns the <ul> class for a given radio_admin value 
    53 get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '') 
    5433 
    5534# Django currently supports two forms of ordering. 
     
    8261            output.append('%s%s ASC' % (prefix, f)) 
    8362    return ', '.join(output) 
    84  
    85 def curry(*args, **kwargs): 
    86     def _curried(*moreargs, **morekwargs): 
    87         return args[0](*(args[1:]+moreargs), **dict(kwargs.items() + morekwargs.items())) 
    88     return _curried 
    8963 
    9064def get_module(app_label, module_name): 
     
    15301504    return new_object 
    15311505 
    1532 def manipulator_validator_unique(f, opts, self, field_data, all_data): 
    1533     "Validates that the value is unique for this field." 
    1534     try: 
    1535         old_obj = opts.get_model_module().get_object(**{'%s__exact' % f.name: field_data}) 
    1536     except ObjectDoesNotExist: 
    1537         return 
    1538     if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.name) == getattr(old_obj, opts.pk.name): 
    1539         return 
    1540     raise validators.ValidationError, "%s with this %s already exists." % (capfirst(opts.verbose_name), f.verbose_name) 
    1541  
    15421506def manipulator_validator_unique_together(field_name_list, opts, self, field_data, all_data): 
    15431507    from django.utils.text import get_text_list 
     
    15841548            raise validators.ValidationError, "Please enter a different %s. The one you entered is already being used for %s." % \ 
    15851549                (from_field.verbose_name, date_val.strftime(format_string)) 
    1586  
    1587 def manipulator_valid_rel_key(f, self, field_data, all_data): 
    1588     "Validates that the value is a valid foreign key" 
    1589     mod = f.rel.to.get_model_module() 
    1590     try: 
    1591         mod.get_object(**{'id__iexact': field_data}) 
    1592     except ObjectDoesNotExist: 
    1593         raise validators.ValidationError, "Please enter a valid %s." % f.verbose_name 
    1594  
    1595 #################### 
    1596 # FIELDS           # 
    1597 #################### 
    1598  
    1599 class Field(object): 
    1600  
    1601     # Designates whether empty strings fundamentally are allowed at the 
    1602     # database level. 
    1603     empty_strings_allowed = True 
    1604  
    1605     def __init__(self, name, verbose_name=None, primary_key=False, 
    1606         maxlength=None, unique=False, blank=False, null=False, db_index=None, 
    1607         core=False, rel=None, default=NOT_PROVIDED, editable=True, 
    1608         prepopulate_from=None, unique_for_date=None, unique_for_month=None, 
    1609         unique_for_year=None, validator_list=None, choices=None, radio_admin=None, 
    1610         help_text=''): 
    1611         self.name = name 
    1612         self.verbose_name = verbose_name or name.replace('_', ' ') 
    1613         self.primary_key = primary_key 
    1614         self.maxlength, self.unique = maxlength, unique 
    1615         self.blank, self.null = blank, null 
    1616         self.core, self.rel, self.default = core, rel, default 
    1617         self.editable = editable 
    1618         self.validator_list = validator_list or [] 
    1619         self.prepopulate_from = prepopulate_from 
    1620         self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month 
    1621         self.unique_for_year = unique_for_year 
    1622         self.choices = choices or [] 
    1623         self.radio_admin = radio_admin 
    1624         self.help_text = help_text 
    1625         if rel and isinstance(rel, ManyToMany): 
    1626             self.help_text += ' Hold down "Control", or "Command" on a Mac, to select more than one.' 
    1627  
    1628         # Set db_index to True if the field has a relationship and doesn't explicitly set db_index. 
    1629         if db_index is None: 
    1630             if isinstance(rel, OneToOne) or isinstance(rel, ManyToOne): 
    1631                 self.db_index = True 
    1632             else: 
    1633                 self.db_index = False 
    1634         else: 
    1635             self.db_index = db_index 
    1636  
    1637     def pre_save(self, obj, value, add): 
    1638         """ 
    1639         Hook for altering the object obj based on the value of this field and 
    1640         and on the add/change status. 
    1641         """ 
    1642         pass 
    1643  
    1644     def get_db_prep_save(self, value, add): 
    1645         "Returns field's value prepared for saving into a database." 
    1646         return value 
    1647  
    1648     def get_db_prep_lookup(self, lookup_type, value): 
    1649         "Returns field's value prepared for database lookup." 
    1650         if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne', 'month', 'day'): 
    1651             return [value] 
    1652         elif lookup_type in ('range', 'in'): 
    1653             return value 
    1654         elif lookup_type == 'year': 
    1655             return ['%s-01-01' % value, '%s-12-31' % value] 
    1656         elif lookup_type in ('contains', 'icontains'): 
    1657             return ["%%%s%%" % prep_for_like_query(value)] 
    1658         elif lookup_type == 'iexact': 
    1659             return [prep_for_like_query(value)] 
    1660         elif lookup_type in ('startswith', 'istartswith'): 
    1661             return ["%s%%" % prep_for_like_query(value)] 
    1662         elif lookup_type in ('endswith', 'iendswith'): 
    1663             return ["%%%s" % prep_for_like_query(value)] 
    1664         elif lookup_type == 'isnull': 
    1665             return [] 
    1666         raise TypeError, "Field has invalid lookup: %s" % lookup_type 
    1667  
    1668     def has_default(self): 
    1669         "Returns a boolean of whether this field has a default value." 
    1670         return self.default != NOT_PROVIDED 
    1671  
    1672     def get_default(self): 
    1673         "Returns the default value for this field." 
    1674         if self.default != NOT_PROVIDED: 
    1675             if hasattr(self.default, '__get_value__'): 
    1676                 return self.default.__get_value__() 
    1677             return self.default 
    1678         if self.null: 
    1679             return None 
    1680         return "" 
    1681  
    1682     def get_manipulator_field_names(self, name_prefix): 
    1683         """ 
    1684         Returns a list of field names that this object adds to the manipulator. 
    1685         """ 
    1686         return [name_prefix + self.name] 
    1687  
    1688     def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False): 
    1689         """ 
    1690         Returns a list of formfields.FormField instances for this field. It 
    1691         calculates the choices at runtime, not at compile time. 
    1692  
    1693         name_prefix is a prefix to prepend to the "field_name" argument. 
    1694         rel is a boolean specifying whether this field is in a related context. 
    1695         """ 
    1696         params = {'validator_list': self.validator_list[:]} 
    1697         if self.maxlength and not self.choices: # Don't give SelectFields a maxlength parameter. 
    1698             params['maxlength'] = self.maxlength 
    1699         if isinstance(self.rel, ManyToOne): 
    1700             if self.rel.raw_id_admin: 
    1701                 field_objs = self.get_manipulator_field_objs() 
    1702                 params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator)) 
    1703             else: 
    1704                 if self.radio_admin: 
    1705                     field_objs = [formfields.RadioSelectField] 
    1706                     params['choices'] = self.get_choices(include_blank=self.blank, blank_choice=BLANK_CHOICE_NONE) 
    1707                     params['ul_class'] = get_ul_class(self.radio_admin) 
    1708                 else: 
    1709                     if self.null: 
    1710                         field_objs = [formfields.NullSelectField] 
    1711                     else: 
    1712                         field_objs = [formfields.SelectField] 
    1713                     params['choices'] = self.get_choices() 
    1714         elif self.choices: 
    1715             if self.radio_admin: 
    1716                 field_objs = [formfields.RadioSelectField] 
    1717                 params['choices'] = self.get_choices(include_blank=self.blank, blank_choice=BLANK_CHOICE_NONE) 
    1718                 params['ul_class'] = get_ul_class(self.radio_admin) 
    1719             else: 
    1720                 field_objs = [formfields.SelectField] 
    1721                 params['choices'] = self.get_choices() 
    1722         else: 
    1723             field_objs = self.get_manipulator_field_objs() 
    1724  
    1725         # Add the "unique" validator(s). 
    1726         for field_name_list in opts.unique_together: 
    1727             if field_name_list[0] == self.name: 
    1728                 params['validator_list'].append(getattr(manipulator, 'isUnique%s' % '_'.join(field_name_list))) 
    1729  
    1730         # Add the "unique for..." validator(s). 
    1731         if self.unique_for_date: 
    1732             params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_date))) 
    1733         if self.unique_for_month: 
    1734             params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_month))) 
    1735         if self.unique_for_year: 
    1736             params['validator_list'].append(getattr(manipulator, 'isUnique%sFor%s' % (self.name, self.unique_for_year))) 
    1737         if self.unique: 
    1738             params['validator_list'].append(curry(manipulator_validator_unique, self, opts, manipulator)) 
    1739  
    1740         # Only add is_required=True if the field cannot be blank. Primary keys 
    1741         # are a special case, and fields in a related context should set this 
    1742         # as False, because they'll be caught by a separate validator -- 
    1743         # RequiredIfOtherFieldGiven. 
    1744         params['is_required'] = not self.blank and not self.primary_key and not rel 
    1745  
    1746         # If this field is in a related context, check whether any other fields 
    1747         # in the related object have core=True. If so, add a validator -- 
    1748         # RequiredIfOtherFieldsGiven -- to this FormField. 
    1749         if rel and not self.blank and not isinstance(self, AutoField) and not isinstance(self, FileField): 
    1750             # First, get the core fields, if any. 
    1751             core_field_names = [] 
    1752             for f in opts.fields: 
    1753                 if f.core and f != self: 
    1754                     core_field_names.extend(f.get_manipulator_field_names(name_prefix)) 
    1755             # Now, if there are any, add the validator to this FormField. 
    1756             if core_field_names: 
    1757                 params['validator_list'].append(validators.RequiredIfOtherFieldsGiven(core_field_names, "This field is required.")) 
    1758  
    1759         # BooleanFields (CheckboxFields) are a special case. They don't take 
    1760         # is_required or validator_list. 
    1761         if isinstance(self, BooleanField): 
    1762             del params['validator_list'], params['is_required'] 
    1763  
    1764         # Finally, add the field_names. 
    1765         field_names = self.get_manipulator_field_names(name_prefix) 
    1766         return [man(field_name=field_names[i], **params) for i, man in enumerate(field_objs)] 
    1767  
    1768     def get_manipulator_new_data(self, new_data, rel=False): 
    1769         """ 
    1770         Given the full new_data dictionary (from the manipulator), returns this 
    1771         field's data. 
    1772         """ 
    1773         if rel: 
    1774             return new_data.get(self.name, [self.get_default()])[0] 
    1775         else: 
    1776             val = new_data.get(self.name, self.get_default()) 
    1777             if not self.empty_strings_allowed and val == '' and self.null: 
    1778                 val = None 
    1779             return val 
    1780  
    1781     def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH): 
    1782         "Returns a list of tuples used as SelectField choices for this field." 
    1783         first_choice = include_blank and blank_choice or [] 
    1784         if self.choices: 
    1785             return first_choice + list(self.choices) 
    1786         rel_obj = self.rel.to 
    1787         return first_choice + [(getattr(x, rel_obj.pk.name), repr(x)) for x in rel_obj.get_model_module().get_list(**self.rel.limit_choices_to)] 
    1788  
    1789 class AutoField(Field): 
    1790     empty_strings_allowed = False 
    1791     def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False): 
    1792         if not rel: 
    1793             return [] # Don't add a FormField unless it's in a related context. 
    1794         return Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel) 
    1795  
    1796     def get_manipulator_field_objs(self): 
    1797         return [formfields.HiddenField] 
    1798  
    1799     def get_manipulator_new_data(self, new_data, rel=False): 
    1800         if not rel: 
    1801             return None 
    1802         return Field.get_manipulator_new_data(self, new_data, rel) 
    1803  
    1804 class BooleanField(Field): 
    1805     def __init__(self, *args, **kwargs): 
    1806         kwargs['blank'] = True 
    1807         Field.__init__(self, *args, **kwargs) 
    1808  
    1809     def get_manipulator_field_objs(self): 
    1810         return [formfields.CheckboxField] 
    1811  
    1812 class CharField(Field): 
    1813     def get_manipulator_field_objs(self): 
    1814         return [formfields.TextField] 
    1815  
    1816 class CommaSeparatedIntegerField(CharField): 
    1817     def get_manipulator_field_objs(self): 
    1818         return [formfields.CommaSeparatedIntegerField] 
    1819  
    1820 class DateField(Field): 
    1821     empty_strings_allowed = False 
    1822     def __init__(self, name, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs): 
    1823         self.auto_now, self.auto_now_add = auto_now, auto_now_add 
    1824         if auto_now or auto_now_add: 
    1825             kwargs['editable'] = False 
    1826         Field.__init__(self, name, verbose_name, **kwargs) 
    1827  
    1828     def get_db_prep_lookup(self, lookup_type, value): 
    1829         if lookup_type == 'range': 
    1830             value = [str(v) for v in value] 
    1831         else: 
    1832             value = str(value) 
    1833         return Field.get_db_prep_lookup(self, lookup_type, value) 
    1834  
    1835     def pre_save(self, obj, value, add): 
    1836         if self.auto_now or (self.auto_now_add and add): 
    1837             setattr(obj, self.name, datetime.datetime.now()) 
    1838  
    1839     def get_db_prep_save(self, value, add): 
    1840         # Casts dates into string format for entry into database. 
    1841         if value is not None: 
    1842             value = value.strftime('%Y-%m-%d') 
    1843         return Field.get_db_prep_save(self, value, add) 
    1844  
    1845     def get_manipulator_field_objs(self): 
    1846         return [formfields.DateField] 
    1847  
    1848 class DateTimeField(DateField): 
    1849     def get_db_prep_save(self, value, add): 
    1850         # Casts dates into string format for entry into database. 
    1851         if value is not None: 
    1852             value = value.strftime('%Y-%m-%d %H:%M:%S') 
    1853         return Field.get_db_prep_save(self, value, add) 
    1854  
    1855     def get_manipulator_field_objs(self): 
    1856         return [formfields.DateField, formfields.TimeField] 
    1857  
    1858     def get_manipulator_field_names(self, name_prefix): 
    1859         return [name_prefix + self.name + '_date', name_prefix + self.name + '_time'] 
    1860  
    1861     def get_manipulator_new_data(self, new_data, rel=False): 
    1862         date_field, time_field = self.get_manipulator_field_names('') 
    1863         if rel: 
    1864             d = new_data.get(date_field, [None])[0] 
    1865             t = new_data.get(time_field, [None])[0] 
    1866         else: 
    1867             d = new_data.get(date_field, None) 
    1868             t = new_data.get(time_field, None) 
    1869         if d is not None and t is not None: 
    1870             return datetime.datetime.combine(d, t) 
    1871         return self.get_default() 
    1872  
    1873 class EmailField(Field): 
    1874     def get_manipulator_field_objs(self): 
    1875         return [formfields.EmailField] 
    1876  
    1877 class FileField(Field): 
    1878     def __init__(self, name, verbose_name=None, upload_to='', **kwargs): 
    1879         self.upload_to = upload_to 
    1880         Field.__init__(self, name, verbose_name, **kwargs) 
    1881  
    1882     def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False): 
    1883         field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel) 
    1884  
    1885         if not self.blank: 
    1886             if rel: 
    1887                 # This validator makes sure FileFields work in a related context. 
    1888                 class RequiredFileField: 
    1889                     def __init__(self, other_field_names, other_file_field_name): 
    1890                         self.other_field_names = other_field_names 
    1891                         self.other_file_field_name = other_file_field_name 
    1892                         self.always_test = True 
    1893                     def __call__(self, field_data, all_data): 
    1894                         if not all_data.get(self.other_file_field_name, False): 
    1895                             c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, "This field is required.") 
    1896                             c(field_data, all_data) 
    1897                 # First, get the core fields, if any. 
    1898                 core_field_names = [] 
    1899                 for f in opts.fields: 
    1900                     if f.core and f != self: 
    1901                         core_field_names.extend(f.get_manipulator_field_names(name_prefix)) 
    1902                 # Now, if there are any, add the validator to this FormField. 
    1903                 if core_field_names: 
    1904                     field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) 
    1905             else: 
    1906                 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, "This field is required.") 
    1907                 v.always_test = True 
    1908                 field_list[0].validator_list.append(v) 
    1909                 field_list[0].is_required = field_list[1].is_required = False 
    1910  
    1911         # If the raw path is passed in, validate it's under the MEDIA_ROOT. 
    1912         def isWithinMediaRoot(field_data, all_data): 
    1913             f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) 
    1914             if not f.startswith(os.path.normpath(settings.MEDIA_ROOT)): 
    1915                 raise validators.ValidationError, "Enter a valid filename." 
    1916         field_list[1].validator_list.append(isWithinMediaRoot) 
    1917         return field_list 
    1918  
    1919     def get_manipulator_field_objs(self): 
    1920         return [formfields.FileUploadField, formfields.HiddenField] 
    1921  
    1922     def get_manipulator_field_names(self, name_prefix): 
    1923         return [name_prefix + self.name + '_file', name_prefix + self.name] 
    1924  
    1925     def save_file(self, new_data, new_object, original_object, change, rel): 
    1926         upload_field_name = self.get_manipulator_field_names('')[0] 
    1927         if new_data.get(upload_field_name, False): 
    1928             if rel: 
    1929                 getattr(new_object, 'save_%s_file' % self.name)(new_data[upload_field_name][0]["filename"], new_data[upload_field_name][0]["content"]) 
    1930             else: 
    1931                 getattr(new_object, 'save_%s_file' % self.name)(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"]) 
    1932  
    1933     def get_directory_name(self): 
    1934         return os.path.normpath(datetime.datetime.now().strftime(self.upload_to)) 
    1935  
    1936     def get_filename(self, filename): 
    1937         from django.utils.text import get_valid_filename 
    1938         f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename))) 
    1939         return os.path.normpath(f) 
    1940  
    1941 class FloatField(Field): 
    1942     empty_strings_allowed = False 
    1943     def __init__(self, name, verbose_name=None, max_digits=None, decimal_places=None, **kwargs): 
    1944         self.max_digits, self.decimal_places = max_digits, decimal_places 
    1945         Field.__init__(self, name, verbose_name, **kwargs) 
    1946  
    1947     def get_manipulator_field_objs(self): 
    1948         return [curry(formfields.FloatField, max_digits=self.max_digits, decimal_places=self.decimal_places)] 
    1949  
    1950 class ImageField(FileField): 
    1951     def __init__(self, name, verbose_name=None, width_field=None, height_field=None, **kwargs): 
    1952         self.width_field, self.height_field = width_field, height_field 
    1953         FileField.__init__(self, name, verbose_name, **kwargs) 
    1954  
    1955     def get_manipulator_field_objs(self): 
    1956         return [formfields.ImageUploadField, formfields.HiddenField] 
    1957  
    1958     def save_file(self, new_data, new_object, original_object, change, rel): 
    1959         FileField.save_file(self, new_data, new_object, original_object, change, rel) 
    1960         # If the image has height and/or width field(s) and they haven't 
    1961         # changed, set the width and/or height field(s) back to their original 
    1962         # values. 
    1963         if change and (self.width_field or self.height_field): 
    1964             if self.width_field: 
    1965                 setattr(new_object, self.width_field, getattr(original_object, self.width_field)) 
    1966             if self.height_field: 
    1967                 setattr(new_object, self.height_field, getattr(original_object, self.height_field)) 
    1968             new_object.save() 
    1969  
    1970 class IntegerField(Field): 
    1971     empty_strings_allowed = False 
    1972     def get_manipulator_field_objs(self): 
    1973         return [formfields.IntegerField] 
    1974  
    1975 class IPAddressField(Field): 
    1976     def __init__(self, *args, **kwargs): 
    1977         kwargs['maxlength'] = 15 
    1978         Field.__init__(self, *args, **kwargs) 
    1979  
    1980     def get_manipulator_field_objs(self): 
    1981         return [formfields.IPAddressField] 
    1982  
    1983 class NullBooleanField(Field): 
    1984     def __init__(self, *args, **kwargs): 
    1985         kwargs['null'] = True 
    1986         Field.__init__(self, *args, **kwargs) 
    1987  
    1988     def get_manipulator_field_objs(self): 
    1989         return [formfields.NullBooleanField] 
    1990  
    1991 class PhoneNumberField(IntegerField): 
    1992     def get_manipulator_field_objs(self): 
    1993         return [formfields.PhoneNumberField] 
    1994  
    1995 class PositiveIntegerField(IntegerField): 
    1996     def get_manipulator_field_objs(self): 
    1997         return [formfields.PositiveIntegerField] 
    1998  
    1999 class PositiveSmallIntegerField(IntegerField): 
    2000     def get_manipulator_field_objs(self): 
    2001         return [formfields.PositiveSmallIntegerField] 
    2002  
    2003 class SlugField(Field): 
    2004     def __init__(self, *args, **kwargs): 
    2005         kwargs['maxlength'] = 50 
    2006         kwargs.setdefault('validator_list', []).append(validators.isAlphaNumeric) 
    2007         # Set db_index=True unless it's been set manually. 
    2008         if not kwargs.has_key('db_index'): 
    2009             kwargs['db_index'] = True 
    2010         Field.__init__(self, *args, **kwargs) 
    2011  
    2012     def get_manipulator_field_objs(self): 
    2013         return [formfields.TextField] 
    2014  
    2015 class SmallIntegerField(IntegerField): 
    2016     def get_manipulator_field_objs(self): 
    2017         return [formfields.SmallIntegerField] 
    2018  
    2019 class TextField(Field): 
    2020     def get_manipulator_field_objs(self): 
    2021         return [formfields.LargeTextField] 
    2022  
    2023 class TimeField(Field): 
    2024     empty_strings_allowed = False 
    2025     def __init__(self, name, verbose_name=None, auto_now=False, auto_now_add=False, **kwargs): 
    2026         self.auto_now, self.auto_now_add  = auto_now, auto_now_add 
    2027         if auto_now or auto_now_add: 
    2028             kwargs['editable'] = False 
    2029         Field.__init__(self, name, verbose_name, **kwargs) 
    2030  
    2031     def get_db_prep_lookup(self, lookup_type, value): 
    2032         if lookup_type == 'range': 
    2033             value = [str(v) for v in value] 
    2034         else: 
    2035             value = str(value) 
    2036         return Field.get_db_prep_lookup(self, lookup_type, value) 
    2037  
    2038     def pre_save(self, obj, value, add): 
    2039         if self.auto_now or (self.auto_now_add and add): 
    2040             setattr(obj, self.name, datetime.datetime.now().time()) 
    2041  
    2042     def get_db_prep_save(self, value, add): 
    2043         # Casts dates into string format for entry into database. 
    2044         if value is not None: 
    2045             value = value.strftime('%H:%M:%S') 
    2046         return Field.get_db_prep_save(self, value, add) 
    2047  
    2048     def get_manipulator_field_objs(self): 
    2049         return [formfields.TimeField] 
    2050  
    2051 class URLField(Field): 
    2052     def __init__(self, name, verbose_name=None, verify_exists=True, **kwargs): 
    2053         if verify_exists: 
    2054             kwargs.setdefault('validator_list', []).append(validators.isExistingURL) 
    2055         Field.__init__(self, name, verbose_name, **kwargs) 
    2056  
    2057     def get_manipulator_field_objs(self): 
    2058         return [formfields.URLField] 
    2059  
    2060 class USStateField(Field): 
    2061     def get_manipulator_field_objs(self): 
    2062         return [formfields.USStateField] 
    2063  
    2064 class XMLField(Field): 
    2065     def __init__(self, name, verbose_name=None, schema_path=None, **kwargs): 
    2066         self.schema_path = schema_path 
    2067         Field.__init__(self, name, verbose_name, **kwargs) 
    2068  
    2069     def get_manipulator_field_objs(self): 
    2070         return [curry(formfields.XMLLargeTextField, schema_path=self.schema_path)] 
    2071  
    2072 class ForeignKey(Field): 
    2073     empty_strings_allowed = False 
    2074     def __init__(self, to, to_field=None, rel_name=None, **kwargs): 
    2075         try: 
    2076             to_name = to._meta.object_name.lower() 
    2077         except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT 
    2078             assert to == 'self', "ForeignKey(%r) is invalid. First parameter to ForeignKey must be either a model or the string %r" % (to, RECURSIVE_RELATIONSHIP_CONSTANT) 
    2079             kwargs['name'] = kwargs.get('name', '') 
    2080             kwargs['verbose_name'] = kwargs.get('verbose_name', '') 
    2081         else: 
    2082             to_field = to_field or to._meta.pk.name 
    2083             kwargs['name'] = kwargs.get('name', to_name + '_id') 
    2084             kwargs['verbose_name'] = kwargs.get('verbose_name', to._meta.verbose_name) 
    2085             rel_name = rel_name or to_name 
    2086         kwargs['rel'] = ManyToOne(to, rel_name, to_field, 
    2087             num_in_admin=kwargs.pop('num_in_admin', 0), 
    2088             min_num_in_admin=kwargs.pop('min_num_in_admin', None), 
    2089             max_num_in_admin=kwargs.pop('max_num_in_admin', None), 
    2090             num_extra_on_change=kwargs.pop('num_extra_on_change', 1), 
    2091             edit_inline=kwargs.pop('edit_inline', False), 
    2092             edit_inline_type=kwargs.pop('edit_inline_type', STACKED), 
    2093             related_name=kwargs.pop('related_name', None), 
    2094             limit_choices_to=kwargs.pop('limit_choices_to', None), 
    2095             lookup_overrides=kwargs.pop('lookup_overrides', None), 
    2096             raw_id_admin=kwargs.pop('raw_id_admin', False)) 
    2097         Field.__init__(self, **kwargs) 
    2098  
    2099     def get_manipulator_field_objs(self): 
    2100         return [formfields.IntegerField] 
    2101  
    2102 class ManyToManyField(Field): 
    2103     def __init__(self, to, rel_name=None, **kwargs): 
    2104         kwargs['name'] = kwargs.get('name', to._meta.module_name) 
    2105         kwargs['verbose_name'] = kwargs.get('verbose_name', to._meta.verbose_name_plural) 
    2106         rel_name = rel_name or to._meta.object_name.lower() 
    2107         kwargs['rel'] = ManyToMany(to, rel_name, 
    2108             num_in_admin=kwargs.pop('num_in_admin', 0), 
    2109             related_name=kwargs.pop('related_name', None), 
    2110             filter_interface=kwargs.pop('filter_interface', None), 
    2111             limit_choices_to=kwargs.pop('limit_choices_to', None)) 
    2112         Field.__init__(self, **kwargs) 
    2113  
    2114     def get_manipulator_field_objs(self): 
    2115         choices = self.get_choices(include_blank=False) 
    2116         return [curry(formfields.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)] 
    2117  
    2118     def get_m2m_db_table(self, original_opts): 
    2119         "Returns the name of the many-to-many 'join' table." 
    2120         return '%s_%s' % (original_opts.db_table, self.name) 
    2121  
    2122 class OneToOneField(IntegerField): 
    2123     def __init__(self, to, to_field=None, rel_name=None, **kwargs): 
    2124         kwargs['name'] = kwargs.get('name', 'id') 
    2125         kwargs['verbose_name'] = kwargs.get('verbose_name', 'ID') 
    2126         to_field = to_field or to._meta.pk.name 
    2127         rel_name = rel_name or to._meta.object_name.lower() 
    2128         kwargs['rel'] = OneToOne(to, rel_name, to_field, 
    2129             num_in_admin=kwargs.pop('num_in_admin', 0), 
    2130             edit_inline=kwargs.pop('edit_inline', False), 
    2131             edit_inline_type=kwargs.pop('edit_inline_type', STACKED), 
    2132             related_name=kwargs.pop('related_name', None), 
    2133             limit_choices_to=kwargs.pop('limit_choices_to', None), 
    2134             lookup_overrides=kwargs.pop('lookup_overrides', None), 
    2135             raw_id_admin=kwargs.pop('raw_id_admin', False)) 
    2136         kwargs['primary_key'] = True 
    2137         IntegerField.__init__(self, **kwargs) 
    2138  
    2139 #################### 
    2140 # RELATIONSHIPS    # 
    2141 #################### 
    2142  
    2143 class ManyToOne: 
    2144     def __init__(self, to, name, field_name, num_in_admin=0, min_num_in_admin=None, 
    2145         max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, edit_inline_type=STACKED, 
    2146         related_name=None, limit_choices_to=None, lookup_overrides=None, raw_id_admin=False): 
    2147         try: 
    2148             self.to = to._meta 
    2149         except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT 
    2150             assert to == RECURSIVE_RELATIONSHIP_CONSTANT, "'to' must be either a model or the string '%s'" % RECURSIVE_RELATIONSHIP_CONSTANT 
    2151             self.to = to 
    2152         self.name, self.field_name = name, field_name 
    2153         self.num_in_admin, self.edit_inline = num_in_admin, edit_inline 
    2154         self.min_num_in_admin, self.max_num_in_admin = min_num_in_admin, max_num_in_admin 
    2155         self.num_extra_on_change = num_extra_on_change 
    2156         self.edit_inline_type, self.related_name = edit_inline_type, related_name 
    2157         self.limit_choices_to = limit_choices_to or {} 
    2158         self.lookup_overrides = lookup_overrides or {} 
    2159         self.raw_id_admin = raw_id_admin 
    2160  
    2161     def get_cache_name(self): 
    2162         return '_%s_cache' % self.name 
    2163  
    2164     def get_related_field(self): 
    2165         "Returns the Field in the 'to' object to which this relationship is tied." 
    2166         return self.to.get_field(self.field_name) 
    2167  
    2168 class ManyToMany: 
    2169     def __init__(self, to, name, num_in_admin=0, related_name=None, 
    2170         filter_interface=None, limit_choices_to=None): 
    2171         self.to, self.name = to._meta, name 
    2172         self.num_in_admin = num_in_admin 
    2173         self.related_name = related_name 
    2174         self.filter_interface = filter_interface 
    2175         self.limit_choices_to = limit_choices_to or {} 
    2176         self.edit_inline = False 
    2177  
    2178 class OneToOne(ManyToOne): 
    2179     def __init__(self, to, name, field_name, num_in_admin=0, edit_inline=False, 
    2180         edit_inline_type=STACKED, related_name=None, limit_choices_to=None, lookup_overrides=None, 
    2181         raw_id_admin=False): 
    2182         self.to, self.name, self.field_name = to._meta, name, field_name 
    2183         self.num_in_admin, self.edit_inline = num_in_admin, edit_inline 
    2184         self.edit_inline_type, self.related_name = edit_inline_type, related_name 
    2185         self.limit_choices_to = limit_choices_to or {} 
    2186         self.lookup_overrides = lookup_overrides or {} 
    2187         self.raw_id_admin = raw_id_admin 
    2188  
    2189 class Admin: 
    2190     def __init__(self, fields=None, js=None, list_display=None, list_filter=None, date_hierarchy=None, 
    2191         save_as=False, ordering=None, search_fields=None, save_on_top=False): 
    2192         self.fields = fields 
    2193         self.js = js or [] 
    2194         self.list_display = list_display or ['__repr__'] 
    2195         self.list_filter = list_filter or [] 
    2196         self.date_hierarchy = date_hierarchy 
    2197         self.save_as, self.ordering = save_as, ordering 
    2198         self.search_fields = search_fields or [] 
    2199         self.save_on_top = save_on_top 
    2200  
    2201     def get_field_objs(self, opts): 
    2202         """ 
    2203         Returns self.fields, except with fields as Field objects instead of 
    2204         field names. If self.fields is None, defaults to putting every 
    2205         non-AutoField field with editable=True in a single fieldset. 
    2206         """ 
    2207         if self.fields is None: 
    2208             field_struct = ((None, {'fields': [f.name for f in opts.fields + opts.many_to_many if f.editable and not isinstance(f, AutoField)]}),) 
    2209         else: 
    2210             field_struct = self.fields 
    2211         new_fieldset_list = [] 
    2212         for fieldset in field_struct: 
    2213             new_fieldset = [fieldset[0], {}] 
    2214             new_fieldset[1].update(fieldset[1]) 
    2215             admin_fields = [] 
    2216             for field_name_or_list in fieldset[1]['fields']: 
    2217                 if isinstance(field_name_or_list, basestring): 
    2218                     admin_fields.append([opts.get_field(field_name_or_list)]) 
    2219                 else: 
    2220                     admin_fields.append([opts.get_field(field_name) for field_name in field_name_or_list]) 
    2221             new_fieldset[1]['fields'] = admin_fields 
    2222             new_fieldset_list.append(new_fieldset) 
    2223         return new_fieldset_list 
  • django/trunk/django/models/__init__.py

    r28 r378  
    11from django.core import meta 
     2from django.utils.functional import curry 
    23 
    34__all__ = ['auth', 'core'] 
     
    2930                # Add "get_thingie" methods for one-to-one related objects. 
    3031                # EXAMPLE: Place.get_restaurants_restaurant() 
    31                 func = meta.curry(meta.method_get_related, 'get_object', rel_mod, rel_field) 
     32                func = curry(meta.method_get_related, 'get_object', rel_mod, rel_field) 
    3233                func.__doc__ = "Returns the associated `%s.%s` object." % (rel_obj.app_label, rel_obj.module_name) 
    3334                setattr(klass, 'get_%s' % rel_obj_name, func) 
     
    3536                # Add "get_thingie" methods for many-to-one related objects. 
    3637                # EXAMPLE: Poll.get_choice() 
    37                 func = meta.curry(meta.method_get_related, 'get_object', rel_mod, rel_field) 
     38                func = curry(meta.method_get_related, 'get_object', rel_mod, rel_field) 
    3839                func.__doc__ = "Returns the associated `%s.%s` object matching the given criteria." % (rel_obj.app_label, rel_obj.module_name) 
    3940                setattr(klass, 'get_%s' % rel_obj_name, func) 
    4041                # Add "get_thingie_count" methods for many-to-one related objects. 
    4142                # EXAMPLE: Poll.get_choice_count() 
    42                 func = meta.curry(meta.method_get_related, 'get_count', rel_mod, rel_field) 
     43                func = curry(meta.method_get_related, 'get_count', rel_mod, rel_field) 
    4344                func.__doc__ = "Returns the number of associated `%s.%s` objects." % (rel_obj.app_label, rel_obj.module_name) 
    4445                setattr(klass, 'get_%s_count' % rel_obj_name, func) 
    4546                # Add "get_thingie_list" methods for many-to-one related objects. 
    4647                # EXAMPLE: Poll.get_choice_list() 
    47                 func = meta.curry(meta.method_get_related, 'get_list', rel_mod, rel_field) 
     48                func = curry(meta.method_get_related, 'get_list', rel_mod, rel_field) 
    4849                func.__doc__ = "Returns a list of associated `%s.%s` objects." % (rel_obj.app_label, rel_obj.module_name) 
    4950                setattr(klass, 'get_%s_list' % rel_obj_name, func) 
     
    5253                # EXAMPLE: Poll.add_choice() 
    5354                if rel_obj.app_label == klass._meta.app_label: 
    54                     func = meta.curry(meta.method_add_related, rel_obj, rel_mod, rel_field) 
     55                    func = curry(meta.method_add_related, rel_obj, rel_mod, rel_field) 
    5556                    func.alters_data = True 
    5657                    setattr(klass, 'add_%s' % rel_obj_name, func) 
     
    6263            rel_mod = rel_opts.get_model_module() 
    6364            rel_obj_name = klass._meta.get_rel_object_method_name(rel_opts, rel_field) 
    64             setattr(klass, 'get_%s' % rel_obj_name, meta.curry(meta.method_get_related_many_to_many, 'get_object', rel_mod, rel_field)) 
    65             setattr(klass, 'get_%s_count' % rel_obj_name, meta.curry(meta.method_get_related_many_to_many, 'get_count', rel_mod, rel_field)) 
    66             setattr(klass, 'get_%s_list' % rel_obj_name, meta.curry(meta.method_get_related_many_to_many, 'get_list', rel_mod, rel_field)) 
     65            setattr(klass, 'get_%s' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_object', rel_mod, rel_field)) 
     66            setattr(klass, 'get_%s_count' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_count', rel_mod, rel_field)) 
     67            setattr(klass, 'get_%s_list' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_list', rel_mod, rel_field)) 
    6768            if rel_opts.app_label == klass._meta.app_label: 
    68                 func = meta.curry(meta.method_set_related_many_to_many, rel_opts, rel_field) 
     69                func = curry(meta.method_set_related_many_to_many, rel_opts, rel_field) 
    6970                func.alters_data = True 
    7071                setattr(klass, 'set_%s' % rel_opts.module_name, func) 
     
    7576        # that are ordered with respect to this. 
    7677        for obj in klass._meta.get_ordered_objects(): 
    77             func = meta.curry(meta.method_set_order, obj) 
     78            func = curry(meta.method_set_order, obj) 
    7879            func.__doc__ = "Sets the order of associated `%s.%s` objects to the given ID list." % (obj.app_label, obj.module_name) 
    7980            func.alters_data = True 
    8081            setattr(klass, 'set_%s_order' % obj.object_name.lower(), func) 
    8182 
    82             func = meta.curry(meta.method_get_order, obj) 
     83            func = curry(meta.method_get_order, obj) 
    8384            func.__doc__ = "Returns the order of associated `%s.%s` objects as a list of IDs." % (obj.app_label, obj.module_name) 
    8485            setattr(klass, 'get_%s_order' % obj.object_name.lower(), func) 
  • django/trunk/django/templatetags/adminapplist.py

    r127 r378  
    77    def render(self, context): 
    88        from django.core import meta 
     9        from django.utils.text import capfirst 
    910        app_list = [] 
    1011        for app in meta.get_installed_model_modules(): 
    1112            app_label = app.__name__[app.__name__.rindex('.')+1:] 
    12             model_list = [{'name': meta.capfirst(m._meta.verbose_name_plural), 
     13            model_list = [{'name': capfirst(m._meta.verbose_name_plural), 
    1314                            'admin_url': '%s/%s/' % (app_label, m._meta.module_name)} \ 
    1415                            for m in app._MODELS if m._meta.admin] 
  • django/trunk/django/utils/text.py

    r175 r378  
    11import re 
     2 
     3# Capitalizes the first letter of a string. 
     4capfirst = lambda x: x and x[0].upper() + x[1:] 
    25 
    36def wrap(text, width): 
  • django/trunk/django/views/admin/main.py

    r340 r378  
    77from django.utils.html impor