Django

Code

Changeset 5463

Show
Ignore:
Timestamp:
06/11/07 10:53:42 (1 year ago)
Author:
bouldersprinters
Message:

boulder-oracle-sprint: Merged to [5462]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/boulder-oracle-sprint/AUTHORS

    r5422 r5463  
    7474    Ian Clelland <clelland@gmail.com> 
    7575    crankycoder@gmail.com 
     76    Pete Crosier <pete.crosier@gmail.com> 
    7677    Matt Croydon <http://www.postneo.com/> 
    7778    flavio.curella@gmail.com 
     
    131132    Antti Kaihola <http://akaihola.blogspot.com/> 
    132133    Ben Dean Kawamura <ben.dean.kawamura@gmail.com> 
     134    ian.g.kelly@gmail.com 
    133135    Garth Kidd <http://www.deadlybloodyserious.com/> 
    134136    kilian <kilian.cavalotti@lip6.fr> 
     
    170172    mmarshall 
    171173    Eric Moritz <http://eric.themoritzfamily.com/> 
     174    mrmachine <real.human@mrmachine.net> 
    172175    Robin Munn <http://www.geekforgod.com/> 
    173176    Robert Myers <myer0052@gmail.com> 
     
    235238    Dan Watson <http://theidioteque.net/> 
    236239    Chris Wesseling <Chris.Wesseling@cwi.nl> 
     240    James Wheare <django@sparemint.com> 
    237241    charly.wilhelm@gmail.com 
    238242    Rachel Willmer <http://www.willmer.com/kb/> 
  • django/branches/boulder-oracle-sprint/django/conf/global_settings.py

    r5384 r5463  
    242242# The User-Agent string to use when checking for URL validity through the 
    243243# isExistingURL validator. 
    244 URL_VALIDATOR_USER_AGENT = "Django/0.96pre (http://www.djangoproject.com)" 
     244from django import get_version 
     245URL_VALIDATOR_USER_AGENT = "Django/%s (http://www.djangoproject.com)" % get_version() 
    245246 
    246247############## 
  • django/branches/boulder-oracle-sprint/django/conf/locale/nl/LC_MESSAGES/django.po

    r4695 r5463  
    22032203 
    22042204#: utils/timesince.py:16 
     2205# In the timesince context it is stilistically wrong to use the plural for hour in Dutch. 
    22052206msgid "hour" 
    22062207msgid_plural "hours" 
    22072208msgstr[0] "uur" 
    2208 msgstr[1] "uren
     2209msgstr[1] "uur
    22092210 
    22102211#: utils/timesince.py:17 
  • django/branches/boulder-oracle-sprint/django/core/management.py

    r5426 r5463  
    44import django 
    55from django.core.exceptions import ImproperlyConfigured 
    6 import os, re, shutil, sys, textwrap 
    76from optparse import OptionParser 
    87from django.utils import termcolors 
     8import os, re, shutil, sys, textwrap 
    99 
    1010# For Python 2.3 
    1111if not hasattr(__builtins__, 'set'): 
    1212    from sets import Set as set 
     13 
     14# For backwards compatibility: get_version() used to be in this module. 
     15get_version = django.get_version 
    1316 
    1417MODULE_TEMPLATE = '''    {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%} 
     
    97100# field as the field to which it points. 
    98101get_rel_data_type = lambda f: (f.get_internal_type() in ('AutoField', 'PositiveIntegerField', 'PositiveSmallIntegerField')) and 'IntegerField' or f.get_internal_type() 
    99  
    100 def get_version(): 
    101     "Returns the version as a human-format string." 
    102     from django import VERSION 
    103     v = '.'.join([str(i) for i in VERSION[:-1]]) 
    104     if VERSION[-1]: 
    105         v += '-' + VERSION[-1] 
    106     return v 
    107102 
    108103def get_sql_create(app): 
  • django/branches/boulder-oracle-sprint/django/db/backends/postgresql/base.py

    r5307 r5463  
    239239    output = [] 
    240240    for model in model_list: 
     241        # Use `coalesce` to set the sequence for each model to the max pk value if there are records, 
     242        # or 1 if there are none. Set the `is_called` property (the third argument to `setval`) to true 
     243        # if there are records (as the max pk value is already in use), otherwise set it to false. 
    241244        for f in model._meta.fields: 
    242245            if isinstance(f, models.AutoField): 
    243                 output.append("%s setval('%s', (%s max(%s) %s %s));" % \ 
     246                output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \ 
    244247                    (style.SQL_KEYWORD('SELECT'), 
    245248                    style.SQL_FIELD(quote_name('%s_%s_seq' % (model._meta.db_table, f.column))), 
    246                     style.SQL_KEYWORD('SELECT'), 
    247249                    style.SQL_FIELD(quote_name(f.column)), 
     250                    style.SQL_FIELD(quote_name(f.column)), 
     251                    style.SQL_KEYWORD('IS NOT'), 
    248252                    style.SQL_KEYWORD('FROM'), 
    249253                    style.SQL_TABLE(quote_name(model._meta.db_table)))) 
    250254                break # Only one AutoField is allowed per model, so don't bother continuing. 
    251255        for f in model._meta.many_to_many: 
    252             output.append("%s setval('%s', (%s max(%s) %s %s));" % \ 
     256            output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \ 
    253257                (style.SQL_KEYWORD('SELECT'), 
    254258                style.SQL_FIELD(quote_name('%s_id_seq' % f.m2m_db_table())), 
    255                 style.SQL_KEYWORD('SELECT'), 
    256259                style.SQL_FIELD(quote_name('id')), 
     260                style.SQL_FIELD(quote_name('id')), 
     261                style.SQL_KEYWORD('IS NOT'), 
    257262                style.SQL_KEYWORD('FROM'), 
    258263                style.SQL_TABLE(f.m2m_db_table()))) 
  • django/branches/boulder-oracle-sprint/django/db/backends/postgresql_psycopg2/base.py

    r5235 r5463  
    196196    output = [] 
    197197    for model in model_list: 
     198        # Use `coalesce` to set the sequence for each model to the max pk value if there are records, 
     199        # or 1 if there are none. Set the `is_called` property (the third argument to `setval`) to true 
     200        # if there are records (as the max pk value is already in use), otherwise set it to false. 
    198201        for f in model._meta.fields: 
    199202            if isinstance(f, models.AutoField): 
    200                 output.append("%s setval('%s', (%s max(%s) %s %s));" % \ 
     203                output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \ 
    201204                    (style.SQL_KEYWORD('SELECT'), 
    202205                    style.SQL_FIELD(quote_name('%s_%s_seq' % (model._meta.db_table, f.column))), 
    203                     style.SQL_KEYWORD('SELECT'), 
    204206                    style.SQL_FIELD(quote_name(f.column)), 
     207                    style.SQL_FIELD(quote_name(f.column)), 
     208                    style.SQL_KEYWORD('IS NOT'), 
    205209                    style.SQL_KEYWORD('FROM'), 
    206210                    style.SQL_TABLE(quote_name(model._meta.db_table)))) 
    207211                break # Only one AutoField is allowed per model, so don't bother continuing. 
    208212        for f in model._meta.many_to_many: 
    209             output.append("%s setval('%s', (%s max(%s) %s %s));" % \ 
     213            output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \ 
    210214                (style.SQL_KEYWORD('SELECT'), 
    211215                style.SQL_FIELD(quote_name('%s_id_seq' % f.m2m_db_table())), 
    212                 style.SQL_KEYWORD('SELECT'), 
    213216                style.SQL_FIELD(quote_name('id')), 
     217                style.SQL_FIELD(quote_name('id')), 
     218                style.SQL_KEYWORD('IS NOT'), 
    214219                style.SQL_KEYWORD('FROM'), 
    215220                style.SQL_TABLE(f.m2m_db_table()))) 
  • django/branches/boulder-oracle-sprint/django/db/backends/util.py

    r5307 r5463  
    9393 
    9494def typecast_decimal(s): 
    95     if s is None
     95    if s is None or s == ''
    9696        return None 
    9797    return decimal.Decimal(s) 
  • django/branches/boulder-oracle-sprint/django/__init__.py

    r4935 r5463  
    11VERSION = (0, 97, 'pre') 
     2 
     3def get_version(): 
     4    "Returns the version as a human-format string." 
     5    v = '.'.join([str(i) for i in VERSION[:-1]]) 
     6    if VERSION[-1]: 
     7        v += '-' + VERSION[-1] 
     8    return v 
  • django/branches/boulder-oracle-sprint/django/template/defaulttags.py

    r5393 r5463  
    66from django.conf import settings 
    77import sys 
     8import re 
     9 
     10if not hasattr(__builtins__, 'reversed'): 
     11    # For Python 2.3. 
     12    # From http://www.python.org/doc/current/tut/node11.html 
     13    def reversed(data): 
     14        for index in xrange(len(data)-1, -1, -1): 
     15            yield data[index] 
     16 
    817 
    918register = Library() 
     
    6271 
    6372class ForNode(Node): 
    64     def __init__(self, loopvar, sequence, reversed, nodelist_loop): 
    65         self.loopvar, self.sequence = loopvar, sequence 
     73    def __init__(self, loopvars, sequence, reversed, nodelist_loop): 
     74        self.loopvars, self.sequence = loopvars, sequence 
    6675        self.reversed = reversed 
    6776        self.nodelist_loop = nodelist_loop 
     
    7382            reversed = '' 
    7483        return "<For Node: for %s in %s, tail_len: %d%s>" % \ 
    75             (self.loopvar, self.sequence, len(self.nodelist_loop), reversed) 
     84            (', '.join( self.loopvars ), self.sequence, len(self.nodelist_loop), reversed) 
    7685 
    7786    def __iter__(self): 
     
    103112        len_values = len(values) 
    104113        if self.reversed: 
    105             # From http://www.python.org/doc/current/tut/node11.html 
    106             def reverse(data): 
    107                 for index in range(len(data)-1, -1, -1): 
    108                     yield data[index] 
    109             values = reverse(values) 
     114            values = reversed(values) 
     115        unpack = len(self.loopvars) > 1 
    110116        for i, item in enumerate(values): 
    111117            context['forloop'] = { 
     
    121127                'parentloop': parentloop, 
    122128            } 
    123             context[self.loopvar] = item 
     129            if unpack: 
     130                # If there are multiple loop variables, unpack the item into them. 
     131                context.update(dict(zip(self.loopvars, item))) 
     132            else: 
     133                context[self.loopvars[0]] = item 
    124134            for node in self.nodelist_loop: 
    125135                nodelist.append(node.render(context)) 
     136            if unpack: 
     137                # The loop variables were pushed on to the context so pop them 
     138                # off again. This is necessary because the tag lets the length 
     139                # of loopvars differ to the length of each set of items and we 
     140                # don't want to leave any vars from the previous loop on the 
     141                # context. 
     142                context.pop() 
    126143        context.pop() 
    127144        return nodelist.render(context) 
     
    487504    parser.delete_first_token() 
    488505    return FilterNode(filter_expr, nodelist) 
    489 filter = register.tag("filter", do_filter) 
     506do_filter = register.tag("filter", do_filter) 
    490507 
    491508#@register.tag 
     
    531548        </ul> 
    532549 
    533     You can also loop over a list in reverse by using 
     550    You can loop over a list in reverse by using 
    534551    ``{% for obj in list reversed %}``. 
     552     
     553    You can also unpack multiple values from a two-dimensional array:: 
     554     
     555        {% for key,value in dict.items %} 
     556            {{ key }}: {{ value }} 
     557        {% endfor %} 
    535558 
    536559    The for loop sets a number of variables available within the loop: 
     
    553576    """ 
    554577    bits = token.contents.split() 
    555     if len(bits) == 5 and bits[4] != 'reversed': 
    556         raise TemplateSyntaxError, "'for' statements with five words should end in 'reversed': %s" % token.contents 
    557     if len(bits) not in (4, 5): 
    558         raise TemplateSyntaxError, "'for' statements should have either four or five words: %s" % token.contents 
    559     if bits[2] != 'in': 
    560         raise TemplateSyntaxError, "'for' statement must contain 'in' as the second word: %s" % token.contents 
    561     loopvar = bits[1] 
    562     sequence = parser.compile_filter(bits[3]) 
    563     reversed = (len(bits) == 5) 
     578    if len(bits) < 4: 
     579        raise TemplateSyntaxError, "'for' statements should have at least four words: %s" % token.contents 
     580 
     581    reversed = bits[-1] == 'reversed' 
     582    in_index = reversed and -3 or -2 
     583    if bits[in_index] != 'in': 
     584        raise TemplateSyntaxError, "'for' statements should use the format 'for x in y': %s" % token.contents 
     585 
     586    loopvars = re.sub(r' *, *', ',', ' '.join(bits[1:in_index])).split(',') 
     587    for var in loopvars: 
     588        if not var or ' ' in var: 
     589            raise TemplateSyntaxError, "'for' tag received an invalid argument: %s" % token.contents 
     590 
     591    sequence = parser.compile_filter(bits[in_index+1]) 
    564592    nodelist_loop = parser.parse(('endfor',)) 
    565593    parser.delete_first_token() 
    566     return ForNode(loopvar, sequence, reversed, nodelist_loop) 
     594    return ForNode(loopvars, sequence, reversed, nodelist_loop) 
    567595do_for = register.tag("for", do_for) 
    568596 
  • django/branches/boulder-oracle-sprint/django/views/debug.py

    r5062 r5463  
    33from django.utils.html import escape 
    44from django.http import HttpResponseServerError, HttpResponseNotFound 
    5 import os, re 
     5import os, re, sys 
    66 
    77HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD|PROFANITIES_LIST') 
     
    132132        'request_protocol': request.is_secure() and "https" or "http", 
    133133        'settings': get_safe_settings(), 
     134        'sys_executable' : sys.executable, 
     135        'sys_version_info' : '%d.%d.%d' % sys.version_info[0:3], 
    134136        'template_info': template_info, 
    135137        'template_does_not_exist': template_does_not_exist, 
     
    335337      <td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td> 
    336338    </tr> 
     339    <tr> 
     340      <th>Python Executable:</th> 
     341      <td>{{ sys_executable|escape }}</td> 
     342    </tr> 
     343    <tr> 
     344      <th>Python Version:</th> 
     345      <td>{{ sys_version_info }}</td> 
     346    </tr> 
    337347  </table> 
    338348</div> 
  • django/branches/boulder-oracle-sprint/docs/add_ons.txt

    r5047 r5463  
    77problems. 
    88 
    9 This code lives in ``django/contrib`` in the Django distribution. Here's a 
    10 rundown of the packages in ``contrib``: 
     9This code lives in ``django/contrib`` in the Django distribution. This document 
     10gives a rundown of the packages in ``contrib``, along with any dependencies 
     11those packages have. 
    1112 
    1213.. admonition:: Note 
     
    2728.. _Tutorial 2: ../tutorial02/ 
    2829 
     30Requires the auth_ and contenttypes_ contrib packages to be installed. 
     31 
    2932auth 
    3033==== 
     
    145148.. _flatpages documentation: ../flatpages/ 
    146149 
     150Requires the sites_ contrib package to be installed as well. 
     151 
    147152localflavor 
    148153=========== 
  • django/branches/boulder-oracle-sprint/docs/authentication.txt

    r5100 r5463  
    731731------------------- 
    732732 
    733 Three basic permissions -- add, create and delete -- are automatically created 
     733Three basic permissions -- add, change and delete -- are automatically created 
    734734for each Django model that has a ``class Admin`` set. Behind the scenes, these 
    735735permissions are added to the ``auth_permission`` database table when you run 
  • django/branches/boulder-oracle-sprint/docs/db-api.txt

    r5384 r5463  
    134134 
    135135The ``save()`` method has no return value. 
     136 
     137Updating ``ForeignKey`` fields works exactly the same way; simply assign an 
     138object of the right type to the field in question:: 
     139 
     140    joe = Author.objects.create(name="Joe") 
     141    entry.author = joe 
     142    entry.save() 
     143     
     144Django will complain if you try to assign an object of the wrong type. 
    136145 
    137146How Django knows to UPDATE vs. INSERT 
     
    380389underlying SQL statement, and the whole thing is enclosed in a ``NOT()``. 
    381390 
    382 This example excludes all entries whose ``pub_date`` is the current date/time 
     391This example excludes all entries whose ``pub_date`` is later than 2005-1-3 
    383392AND whose ``headline`` is "Hello":: 
    384393 
     
    390399    WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello') 
    391400 
    392 This example excludes all entries whose ``pub_date`` is the current date/time 
    393 OR whose ``headline`` is "Hello":: 
     401This example excludes all entries whose ``pub_date`` is later than 2005-1-3 
     402AND whose headline is NOT "Hello":: 
    394403 
    395404    Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello') 
     
    12301239    Blog.objects.filter(entry__headline__contains='Lennon') 
    12311240 
    1232 Escaping parenthesis and underscores in LIKE statements 
    1233 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     1241Escaping percent signs and underscores in LIKE statements 
     1242~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    12341243 
    12351244The field lookups that equate to ``LIKE`` SQL statements (``iexact``, 
  • django/branches/boulder-oracle-sprint/docs/fastcgi.txt

    r4906 r5463  
    204204      Alias /media /home/user/python/django/contrib/admin/media 
    205205      RewriteEngine On 
    206       RewriteRule ^/(media.*)$ /$1 [QSA,L
     206      RewriteRule ^/(media.*)$ /$1 [QSA,L,PT
    207207      RewriteCond %{REQUEST_FILENAME} !-f 
    208208      RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L] 
  • django/branches/boulder-oracle-sprint/docs/model-api.txt

    r5384 r5463  
    447447 
    448448The admin represents this as an ``<input type="text">`` (a single-line input). 
     449 
     450``URLField`` takes an optional argument, ``maxlength``, the maximum length (in 
     451characters) of the field. The maxlength is enforced at the database level and 
     452in Django's validation. If you don't specify ``maxlength``, a default of 200 
     453is used. 
    449454 
    450455``USStateField`` 
     
    18781883        return row 
    18791884 
    1880 ``connection`` and ``cursor`` simply use the standard `Python DB-API`_. If 
    1881 you're not familiar with the Python DB-API, note that the SQL statement in 
    1882 ``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding parameters 
    1883 directly within the SQL. If you use this technique, the underlying database 
    1884 library will automatically add quotes and escaping to your parameter(s) as 
    1885 necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the 
    1886 ``"?"`` placeholder, which is used by the SQLite Python bindings. This is for 
    1887 the sake of consistency and sanity.) 
     1885``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_ 
     1886(except when it comes to `transaction handling`_). If you're not familiar with 
     1887the Python DB-API, note that the SQL statement in ``cursor.execute()`` uses 
     1888placeholders, ``"%s"``, rather than adding parameters directly within the SQL. 
     1889If you use this technique, the underlying database library will automatically 
     1890add quotes and escaping to your parameter(s) as necessary. (Also note that 
     1891Django expects the ``"%s"`` placeholder, *not* the ``"?"`` placeholder, which is 
     1892used by the SQLite Python bindings. This is for the sake of consistency and 
     1893sanity.) 
    18881894 
    18891895A final note: If all you want to do is a custom ``WHERE`` clause, you can just 
     
    18931899.. _Python DB-API: http://www.python.org/peps/pep-0249.html 
    18941900.. _Other lookup options: ../db-api/#extra-params-select-where-tables 
     1901.. _transaction handling: ../transactions/ 
    18951902 
    18961903Overriding default model methods 
  • django/branches/boulder-oracle-sprint/docs/modpython.txt

    r5384 r5463  
    5252 
    5353Also, if you've manually altered your ``PYTHONPATH`` to put your Django project 
    54 on it, you'll need to tell mod_python:: 
    55  
    56     PythonPath "['/path/to/project'] + sys.path" 
     54on it, you'll need to tell mod_python: 
     55 
     56.. parsed-literal:: 
     57 
     58    <Location "/mysite/"> 
     59        SetHandler python-program 
     60        PythonHandler django.core.handlers.modpython 
     61        SetEnv DJANGO_SETTINGS_MODULE mysite.settings 
     62        PythonDebug On 
     63        **PythonPath "['/path/to/project'] + sys.path"** 
     64    </Location> 
    5765 
    5866.. caution:: 
  • django/branches/boulder-oracle-sprint/docs/newforms.txt

    r5384 r5463  
    300300empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat 
    301301empty values as an empty string. Each field type knows what its "blank" value 
    302 is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. 
     302is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. For 
     303full details on each field's behavior in this case, see the "Empty value" note 
     304for each field in the "Built-in ``Field`` classes" section below. 
     305 
     306You can write code to perform validation for particular form fields (based on 
     307their name) or for the form as a whole (considering combinations of various 
     308fields). More information about this is in the `Custom form and field 
     309validation`_ section, below. 
    303310 
    304311Behavior of unbound forms 
    305312~~~~~~~~~~~~~~~~~~~~~~~~~ 
    306313 
    307 It's meaningless to request "clean" data in a form with no data, but, for the 
     314It's meaningless to request "cleaned" data in a form with no data, but, for the 
    308315record, here's what happens with unbound forms:: 
    309316 
     
    607614 
    608615Let's put this all together and use the ``ContactForm`` example in a Django 
    609 view and template. This example view displays the contact form by default and 
    610 validates/processes it if accessed via a POST request:: 
     616view and template. 
     617 
     618Simple view example 
     619~~~~~~~~~~~~~~~~~~~ 
     620 
     621This example view displays the contact form by default and validates/processes 
     622it if accessed via a POST request:: 
    611623 
    612624    def contact(request): 
     
    620632        return render_to_response('contact.html', {'form': form}) 
    621633 
    622 Simple template output 
    623 ~~~~~~~~~~~~~~~~~~~~~~ 
    624  
    625 The template, ``contact.html``, is responsible for displaying the form as HTML. 
    626 To do this, we can use the techniques outlined in the "Outputting forms as HTML" 
    627 section above. 
     634Simple template example 
     635~~~~~~~~~~~~~~~~~~~~~~~ 
     636 
     637The template in the above view example, ``contact.html``, is responsible for 
     638displaying the form as HTML. To do this, we can use the techniques outlined in 
     639the "Outputting forms as HTML" section above. 
    628640 
    629641The simplest way to display a form's HTML is to use the variable on its own, 
     
    678690This iteration technique is useful if you want to apply the same HTML 
    679691formatting to each field, or if you don't know the names of the form fields 
    680 ahead of time. Note that the fields will be listed in the order in which 
     692ahead of time. Note that the fields will be iterated over in the order in which 
    681693they're defined in the ``Form`` class. 
    682694 
     
    702714----------------- 
    703715 
    704 If you subclass a custom ``Form`` class, the resulting ``Form`` class will 
     716If you have multiple ``Form`` classes that share fields, you can use 
     717subclassing to remove redundancy. 
     718 
     719When you subclass a custom ``Form`` class, the resulting subclass will 
    705720include all fields of the parent class(es), followed by the fields you define 
    706721in the subclass. 
     
    12021217mentioned above (``required``, ``label``, ``initial``, ``widget``, 
    12031218``help_text``). 
     1219 
     1220Custom form and field validation 
     1221--------------------------------- 
     1222 
     1223Form validation happens when the data is cleaned. If you want to customise 
     1224this process, there are various places you can change, each one serving a 
     1225different purpose. Thee types of cleaning methods are run during form 
     1226processing. These are normally executed when you call the ``is_valid()`` 
     1227method on a form. There are other things that can kick of cleaning and 
     1228validation (accessing the ``errors`` attribute or calling ``full_clean()`` 
     1229directly), but normally they won't be needed. 
     1230 
     1231In general, any cleaning method can raise ``ValidationError`` if there is a 
     1232problem with the data it is processing, passing the relevant error message to 
     1233the ``ValidationError`` constructor. If no ``ValidationError`` is raised, the 
     1234method should return the cleaned (normalised) data as a Python object. 
     1235 
     1236If you detect multiple errors during a cleaning method and wish to signal all 
     1237of them to the form submittor, it is possible to pass a list of errors to the 
     1238``ValidationError`` constructor. 
     1239 
     1240The three types of cleaning methods are: 
     1241 
     1242    * The ``clean()`` method on a Field subclass. This is responsible 
     1243      for cleaning the data in a way that is generic for that type of field. 
     1244      For example, a FloatField will turn the data into a Python ``float`` or 
     1245      raise a ``ValidationError``. 
     1246 
     1247    * The ``clean_<fieldname>()`` method in a form subclass -- where 
     1248      ``<fieldname>`` is replaced with the name of the form field attribute. 
     1249      This method does any cleaning that is specific to that particular 
     1250      attribute, unrelated to the type of field that it is. This method is not 
     1251      passed any parameters. You will need to look up the value of the field 
     1252      in ``self.cleaned_data`` and remember that it will be a Python object 
     1253      at this point, not the original string submitted in the form (it will be 
     1254      in ``cleaned_data`` because the general field ``clean()`` method, above, 
     1255      has already cleaned the data once). 
     1256 
     1257      For example, if you wanted to validate that the contents of a 
     1258      ``CharField`` called ``serialnumber`` was unique, 
     1259      ``clean_serialnumber()`` would be the right place to do this. You don't 
     1260      need a specific field (it's just a ``CharField``), but you want a 
     1261      formfield-specific piece of validation and, possibly, 
     1262      cleaning/normalizing the data. 
     1263 
     1264    * The Form subclass's ``clean()`` method. This method can perform 
     1265      any validation that requires access to multiple fields from the form at 
     1266      once. This is where you might put in things to check that if field ``A`` 
     1267      is supplied, field ``B`` must contain a valid email address and the 
     1268      like. The data that this method returns is the final ``cleaned_data`` 
     1269      attribute for the form, so don't forget to return the full list of 
     1270      cleaned data if you override this method (by default, ``Form.clean()`` 
     1271      just returns ``self.cleaned_data``). 
     1272 
     1273      Note that any errors raised by your ``Form.clean()`` override will not 
     1274      be associated with any field in particular. They go into a special 
     1275      "field" (called ``__all__``, which you can access via the 
     1276      ``non_field_errors()`` method if you need to. 
     1277 
     1278These methods are run in the order given above, one field at a time.  That is, 
     1279for each field in the form (in the order they are declared in the form 
     1280definition), the ``Field.clean()`` method (or it's override) is run, then 
     1281``clean_<fieldname>()``. Finally, once those two methods are run for every 
     1282field, the ``Form.clean()`` method, or it's override, is executed. 
     1283 
     1284As mentioned above, any of these methods can raise a ``ValidationError``. For 
     1285any field, if the ``Field.clean()`` method raises a ``ValidationError``, any 
     1286field-specific cleaning method is not called. However, the cleaning methods 
     1287for all remaining fields are still executed. 
     1288 
     1289The ``clean()`` method for the ``Form`` class or subclass is always run. If 
     1290that method raises a ``ValidationError``, ``cleaned_data`` will be an empty 
     1291dictionary. 
     1292 
     1293The previous paragraph means that if you are overriding ``Form.clean()``, you 
     1294should iterate through ``self.cleaned_data.items()``, possibly considering the 
     1295``_errors`` dictionary attribute on the form as well. In this way, you will 
     1296already know which fields have passed thei individual validation requirements. 
     1297 
     1298A simple example 
     1299~~~~~~~~~~~~~~~~ 
     1300 
     1301Here's a simple example of a custom field that validates its input is a string 
     1302containing comma-separated e-mail addresses, with at least one address. We'll 
     1303keep it simple and assume e-mail validation is contained in a function called 
     1304``is_valid_email()``. The full class:: 
     1305 
     1306    from django import newforms as forms 
     1307 
     1308    class MultiEmailField(forms.Field): 
     1309        def clean(self, value): 
     1310            emails = value.split(',') 
     1311            for email in emails: 
     1312                if not is_valid_email(email): 
     1313                    raise forms.ValidationError('%s is not a valid e-mail address.' % email) 
     1314            if not emails: 
     1315                raise forms.ValidationError('Enter at least one e-mail address.') 
     1316            return emails 
     1317 
     1318Let's alter the ongoing ``ContactForm`` example to demonstrate how you'd use 
     1319this in a form. Simply use ``MultiEmailField`` instead of ``forms.EmailField``, 
     1320like so:: 
     1321 
     1322    class ContactForm(forms.Form): 
     1323        subject = forms.CharField(max_length=100) 
     1324        message = forms.CharField() 
     1325        senders = MultiEmailField() 
     1326        cc_myself = forms.BooleanField() 
    12041327 
    12051328Generating forms for models 
  • django/branches/boulder-oracle-sprint/docs/templates.txt

    r5384 r5463  
    9292then converting line breaks to ``<p>`` tags. 
    9393 
    94 Some filters take arguments. A filter argument looks like this: 
    95 ``{{ bio|truncatewords:"30" }}``. This will display the first 30 words of the 
    96 ``bio`` variable. Filter arguments always are in double quotes. 
     94Some filters take arguments. A filter argument looks like this: ``{{ 
     95bio|truncatewords:30 }}``. This will display the first 30 words of the ``bio`` 
     96variable. 
     97 
     98Filter arguments that contain spaces must be quoted; for example, to join a list 
     99with commas and spaced you'd use ``{{ list|join:", " }}``. 
    97100 
    98101The `Built-in filter reference`_ below describes all the built-in filters. 
     
    445448 
    446449Loop over each item in an array.  For example, to display a list of athletes 
    447 given ``athlete_list``:: 
     450provided in ``athlete_list``:: 
    448451 
    449452    <ul> 
     
    453456    </ul> 
    454457 
    455 You can also loop over a list in reverse by using ``{% for obj in list reversed %}``. 
     458You can loop over a list in reverse by using ``{% for obj in list reversed %}``. 
     459 
     460**New in Django development version** 
     461If you need to loop over a list of lists, you can unpack the values 
     462in eachs sub-list into a set of known names. For example, if your context contains 
     463a list of (x,y) coordinates called ``points``, you could use the following 
     464to output the list of points::  
     465 
     466    {% for x, y in points %} 
     467        There is a point at {{ x }},{{ y }} 
     468    {% endfor %} 
     469     
     470This can also be useful if you need to access the items in a dictionary.  
     471For example, if your context contained a dictionary ``data``, the following 
     472would display the keys and values of the dictionary:: 
     473 
     474    {% for key, value in data.items %} 
     475        {{ key }}: {{ value }} 
     476    {% endfor %} 
    456477 
    457478The for loop sets a number of variables available within the loop: 
  • django/branches/boulder-oracle-sprint/scripts/rpm-install.sh

    r4935 r5463  
    2222sed -e "/\.py[co]$/d" -e "s/\.py$/.py*/" DIRS FILES >INSTALLED_FILES 
    2323 
     24mkdir -p ${RPM_BUILD_ROOT}/%{_mandir}/man1/ 
     25cp docs/man/* ${RPM_BUILD_ROOT}/%{_mandir}/man1/ 
     26cat << EOF >> INSTALLED_FILES 
     27%doc %{_mandir}/man1/*" 
     28EOF 
  • django/branches/boulder-oracle-sprint/tests/regressiontests/serializers_regress/tests.py

    r5422 r5463  
    303303    obj = ComplexModel(field1='first',field2='second',field3='third') 
    304304    obj.save() 
    305      
     305 
    306306    # Serialize then deserialize the test database 
    307307    serialized_data = serializers.serialize(format, [obj], indent=2, fields=('field1','field3')) 
    308308    result = serializers.deserialize(format, serialized_data).next() 
    309      
     309 
    310310    # Check that the deserialized object contains data in only the serialized fields. 
    311311    self.assertEqual(result.object.field1, 'first') 
     
    319319    obj = ComplexModel(field1='first',field2='second',field3='third') 
    320320    obj.save() 
    321      
     321 
    322322    # Serialize the test database to a stream 
    323     stream = StringIO()     
     323    stream = StringIO() 
    324324    serializers.serialize(format, [obj], indent=2, stream=stream) 
    325      
     325 
    326326    # Serialize normally for a comparison 
    327327    string_data = serializers.serialize(format, [obj], indent=2) 
    328328 
    329329    # Check that the two are the same 
    330     self.assertEqual(string_data, stream.buffer()) 
     330    self.assertEqual(string_data, stream.getvalue()) 
    331331    stream.close() 
    332      
     332 
    333333for format in serializers.get_serializer_formats(): 
    334334    setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format)) 
    335335    setattr(SerializerTests, 'test_'+format+'_serializer_fields', curry(fieldsTest, format)) 
    336     setattr(SerializerTests, 'test_'+format+'_serializer_stream', curry(fieldsTest, format)) 
     336    if format != 'python': 
     337        setattr(SerializerTests, 'test_'+format+'_serializer_stream', curry(streamTest, format)) 
  • django/branches/boulder-oracle-sprint/tests/regressiontests/templates/tests.py

    r5174 r5463  
    290290            'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"), 
    291291            'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"), 
     292            'for-tag-unpack01': ("{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 
     293            'for-tag-unpack03': ("{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 
     294            'for-tag-unpack04': ("{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 
     295            'for-tag-unpack05': ("{% for key ,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 
     296            'for-tag-unpack06': ("{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 
     297            'for-tag-unpack07': ("{% for key,,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 
     298            'for-tag-unpack08': ("{% for key,value, in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 
     299            # Ensure that a single loopvar doesn't truncate the list in val. 
     300            'for-tag-unpack09': ("{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 
     301            # Otherwise, silently truncate if the length of loopvars differs to the length of each set of items. 
     302            'for-tag-unpack10': ("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'orange'))}, "one:1/two:2/"), 
     303            'for-tag-unpack11': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, ("one:1,/two:2,/", "one:1,INVALID/two:2,INVALID/")), 
     304            'for-tag-unpack12': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2))}, ("one:1,carrot/two:2,/", "one:1,carrot/two:2,INVALID/")), 
     305            'for-tag-unpack13': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'cheese'))}, ("one:1,carrot/two:2,cheese/", "one:1,carrot/two:2,cheese/")), 
    292306 
    293307            ### IF TAG ################################################################