mirror of
https://github.com/django/django.git
synced 2025-07-06 10:49:17 +00:00
queryset-refactor: Merged to [6155]
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6332 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
c8f6e485b8
commit
fb6a0c8ffa
2
AUTHORS
2
AUTHORS
@ -127,6 +127,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Dimitris Glezos <dimitris@glezos.com>
|
||||
glin@seznam.cz
|
||||
martin.glueck@gmail.com
|
||||
Artyom Gnilov <boobsd@gmail.com>
|
||||
GomoX <gomo@datafull.com>
|
||||
Mario Gonzalez <gonzalemario@gmail.com>
|
||||
pradeep.gowda@gmail.com
|
||||
@ -240,6 +241,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Jan Rademaker
|
||||
Michael Radziej <mir@noris.de>
|
||||
Amit Ramon <amit.ramon@gmail.com>
|
||||
Philippe Raoult <philippe.raoult@n2nsoft.com>
|
||||
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
|
||||
Brian Ray <http://brianray.chipy.org/>
|
||||
remco@diji.biz
|
||||
|
@ -40,6 +40,9 @@ var RUSSIAN_MAP = {
|
||||
'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
|
||||
'Я':'Ya'
|
||||
}
|
||||
var UKRAINIAN_MAP = {
|
||||
'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g'
|
||||
}
|
||||
var CZECH_MAP = {
|
||||
'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
|
||||
'ž':'z'
|
||||
@ -51,7 +54,8 @@ ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
|
||||
ALL_DOWNCODE_MAPS[2]=GREEK_MAP
|
||||
ALL_DOWNCODE_MAPS[3]=TURKISH_MAP
|
||||
ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP
|
||||
ALL_DOWNCODE_MAPS[5]=CZECH_MAP
|
||||
ALL_DOWNCODE_MAPS[5]=UKRAINIAN_MAP
|
||||
ALL_DOWNCODE_MAPS[6]=CZECH_MAP
|
||||
|
||||
var Downcoder = new Object();
|
||||
Downcoder.Initialize = function()
|
||||
|
@ -10,7 +10,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for result in results %}
|
||||
<tr class="{% cycle row1,row2 %}">{% for item in result %}{{ item }}{% endfor %}</tr>
|
||||
<tr class="{% cycle 'row1' 'row2' %}">{% for item in result %}{{ item }}{% endfor %}</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for field in field_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for year in date_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ year.year }}/">{{ year.year }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ year.year }}/">{{ year.year }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for month in date_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for choice in field.choices %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for field in field_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object|iriencode }}/">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object|iriencode }}/">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
{% block content %}
|
||||
|
||||
{% for model in model_list %}
|
||||
<div class="modelgroup {% cycle even,odd %}">
|
||||
<div class="modelgroup {% cycle 'even' 'odd' %}">
|
||||
<h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2>
|
||||
<p>
|
||||
{% for object in model.sample_objects %}
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
<ul class="objectlist">
|
||||
{% for object in model.objects %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<table class="objectinfo">
|
||||
{% for field in object.fields %}
|
||||
<tr class="{% cycle odd,even %}">
|
||||
<tr class="{% cycle 'odd' 'even' %}">
|
||||
<th>{{ field.field.verbose_name|capfirst }}</th>
|
||||
<td>
|
||||
{% if field.urls %}
|
||||
@ -29,7 +29,7 @@
|
||||
{% if related_object.object_list %}
|
||||
<ul class="objectlist">
|
||||
{% for object in related_object.object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
|
0
django/contrib/localflavor/ar/__init__.py
Normal file
0
django/contrib/localflavor/ar/__init__.py
Normal file
36
django/contrib/localflavor/ar/ar_provinces.py
Normal file
36
django/contrib/localflavor/ar/ar_provinces.py
Normal file
@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
A list of Argentinean provinces and autonomous cities as `choices` in a
|
||||
formfield. From
|
||||
http://www.argentina.gov.ar/argentina/portal/paginas.dhtml?pagina=425
|
||||
|
||||
This exists in this standalone file so that it's only imported into memory
|
||||
when explicitly needed.
|
||||
"""
|
||||
|
||||
PROVINCE_CHOICES = (
|
||||
('B', u'Buenos Aires'),
|
||||
('K', u'Catamarca'),
|
||||
('H', u'Chaco'),
|
||||
('U', u'Chubut'),
|
||||
('C', u'Ciudad Autónoma de Buenos Aires'),
|
||||
('X', u'Córdoba'),
|
||||
('W', u'Corrientes'),
|
||||
('E', u'Entre Ríos'),
|
||||
('P', u'Formosa'),
|
||||
('Y', u'Jujuy'),
|
||||
('L', u'La Pampa'),
|
||||
('F', u'La Rioja'),
|
||||
('M', u'Mendoza'),
|
||||
('N', u'Misiones'),
|
||||
('Q', u'Neuquén'),
|
||||
('R', u'Río Negro'),
|
||||
('A', u'Salta'),
|
||||
('J', u'San Juan'),
|
||||
('D', u'San Luis'),
|
||||
('Z', u'Santa Cruz'),
|
||||
('S', u'Santa Fe'),
|
||||
('G', u'Santiago del Estero'),
|
||||
('V', u'Tierra del Fuego, Antártida e Islas del Atlántico Sur'),
|
||||
('T', u'Tucumán'),
|
||||
)
|
105
django/contrib/localflavor/ar/forms.py
Normal file
105
django/contrib/localflavor/ar/forms.py
Normal file
@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
AR-specific Form helpers.
|
||||
"""
|
||||
|
||||
from django.newforms import ValidationError
|
||||
from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES
|
||||
from django.utils.encoding import smart_unicode
|
||||
from django.utils.translation import ugettext
|
||||
import re
|
||||
|
||||
class ARProvinceSelect(Select):
|
||||
"""
|
||||
A Select widget that uses a list of Argentinean provinces/autonomous cities
|
||||
as its choices.
|
||||
"""
|
||||
def __init__(self, attrs=None):
|
||||
from ar_provinces import PROVINCE_CHOICES
|
||||
super(ARProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
|
||||
|
||||
class ARPostalCodeField(RegexField):
|
||||
"""
|
||||
A field that accepts a `classic´ NNNN Postal Code or a CPA.
|
||||
|
||||
See http://www.correoargentino.com.ar/consulta_cpa/home.php
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ARPostalCodeField, self).__init__(r'^\d{4}$|^[A-HJ-NP-Za-hj-np-z]\d{4}\D{3}$',
|
||||
min_length=4, max_length=8,
|
||||
error_message=ugettext("Enter a postal code in the format NNNN or ANNNNAAA."),
|
||||
*args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
value = super(ARPostalCodeField, self).clean(value)
|
||||
if value in EMPTY_VALUES:
|
||||
return u''
|
||||
if len(value) not in (4, 8):
|
||||
raise ValidationError(ugettext("Enter a postal code in the format NNNN or ANNNNAAA."))
|
||||
if len(value) == 8:
|
||||
return u'%s%s%s' % (value[0].upper(), value[1:5], value[5:].upper())
|
||||
return value
|
||||
|
||||
class ARDNIField(CharField):
|
||||
"""
|
||||
A field that validates `Documento Nacional de Identidad´ (DNI) numbers.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ARDNIField, self).__init__(max_length=10, min_length=7, *args,
|
||||
**kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Value can be a string either in the [X]X.XXX.XXX or [X]XXXXXXX formats.
|
||||
"""
|
||||
value = super(ARDNIField, self).clean(value)
|
||||
if value in EMPTY_VALUES:
|
||||
return u''
|
||||
if not value.isdigit():
|
||||
value = value.replace('.', '')
|
||||
if not value.isdigit():
|
||||
raise ValidationError(ugettext("This field requires only numbers."))
|
||||
if len(value) not in (7, 8):
|
||||
raise ValidationError(
|
||||
ugettext("This field requires 7 or 8 digits."))
|
||||
|
||||
return value
|
||||
|
||||
class ARCUITField(RegexField):
|
||||
"""
|
||||
This field validates a CUIT (Código Único de Identificación Tributaria). A
|
||||
CUIT is of the form XX-XXXXXXXX-V. The last digit is a check digit.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ARCUITField, self).__init__(r'^\d{2}-?\d{8}-?\d$',
|
||||
error_message=ugettext('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'),
|
||||
*args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Value can be either a string in the format XX-XXXXXXXX-X or an
|
||||
11-digit number.
|
||||
"""
|
||||
value = super(ARCUITField, self).clean(value)
|
||||
if value in EMPTY_VALUES:
|
||||
return u''
|
||||
value, cd = self._canon(value)
|
||||
if self._calc_cd(value) != cd:
|
||||
raise ValidationError(ugettext("Invalid CUIT."))
|
||||
return self._format(value, cd)
|
||||
|
||||
def _canon(self, cuit):
|
||||
cuit = cuit.replace('-', '')
|
||||
return cuit[:-1], cuit[-1]
|
||||
|
||||
def _calc_cd(self, cuit):
|
||||
mults = (5, 4, 3, 2, 7, 6, 5, 4, 3, 2)
|
||||
tmp = sum([m * int(cuit[idx]) for idx, m in enumerate(mults)])
|
||||
return str(11 - tmp % 11)
|
||||
|
||||
def _format(self, cuit, check_digit=None):
|
||||
if check_digit == None:
|
||||
check_digit = cuit[-1]
|
||||
cuit = cuit[:-1]
|
||||
return u'%s-%s-%s' % (cuit[:2], cuit[2:], check_digit)
|
||||
|
@ -20,6 +20,7 @@ class ObjectPaginator(object):
|
||||
self.num_per_page = num_per_page
|
||||
self.orphans = orphans
|
||||
self._hits = self._pages = None
|
||||
self._page_range = None
|
||||
|
||||
def validate_page_number(self, page_number):
|
||||
try:
|
||||
@ -83,6 +84,16 @@ class ObjectPaginator(object):
|
||||
hits = 0
|
||||
self._pages = hits // self.num_per_page + 1
|
||||
return self._pages
|
||||
|
||||
def _get_page_range(self):
|
||||
"""
|
||||
Returns a 1-based range of pages for iterating through within
|
||||
a template for loop.
|
||||
"""
|
||||
if self._page_range is None:
|
||||
self._page_range = range(1, self._pages + 1)
|
||||
return self._page_range
|
||||
|
||||
hits = property(_get_hits)
|
||||
pages = property(_get_pages)
|
||||
page_range = property(_get_page_range)
|
||||
|
@ -855,6 +855,7 @@ class ImageField(FileField):
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {'form_class': forms.ImageField}
|
||||
defaults.update(kwargs)
|
||||
return super(ImageField, self).formfield(**defaults)
|
||||
|
||||
class IntegerField(Field):
|
||||
|
@ -335,12 +335,6 @@ class EmailField(RegexField):
|
||||
RegexField.__init__(self, email_re, max_length, min_length,
|
||||
ugettext(u'Enter a valid e-mail address.'), *args, **kwargs)
|
||||
|
||||
url_re = re.compile(
|
||||
r'^https?://' # http:// or https://
|
||||
r'(?:[A-Z0-9-]+\.)+[A-Z]{2,6}' # domain
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|/\S+)$', re.IGNORECASE)
|
||||
|
||||
try:
|
||||
from django.conf import settings
|
||||
URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT
|
||||
@ -399,6 +393,14 @@ class ImageField(FileField):
|
||||
raise ValidationError(ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."))
|
||||
return f
|
||||
|
||||
url_re = re.compile(
|
||||
r'^https?://' # http:// or https://
|
||||
r'(?:(?:[A-Z0-9-]+\.)+[A-Z]{2,6}|' #domain...
|
||||
r'localhost|' #localhost...
|
||||
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|/\S+)$', re.IGNORECASE)
|
||||
|
||||
class URLField(RegexField):
|
||||
def __init__(self, max_length=None, min_length=None, verify_exists=False,
|
||||
validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs):
|
||||
|
@ -57,13 +57,15 @@ class BaseForm(StrAndUnicode):
|
||||
# class is different than Form. See the comments by the Form class for more
|
||||
# information. Any improvements to the form API should be made to *this*
|
||||
# class, not to the Form class.
|
||||
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None):
|
||||
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
|
||||
initial=None, error_class=ErrorList):
|
||||
self.is_bound = data is not None or files is not None
|
||||
self.data = data or {}
|
||||
self.files = files or {}
|
||||
self.auto_id = auto_id
|
||||
self.prefix = prefix
|
||||
self.initial = initial or {}
|
||||
self.error_class = error_class
|
||||
self._errors = None # Stores the errors after clean() has been called.
|
||||
|
||||
# The base_fields class attribute is the *class-wide* definition of
|
||||
@ -117,7 +119,7 @@ class BaseForm(StrAndUnicode):
|
||||
output, hidden_fields = [], []
|
||||
for name, field in self.fields.items():
|
||||
bf = BoundField(self, field, name)
|
||||
bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable.
|
||||
bf_errors = self.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable.
|
||||
if bf.is_hidden:
|
||||
if bf_errors:
|
||||
top_errors.extend(['(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors])
|
||||
@ -168,7 +170,7 @@ class BaseForm(StrAndUnicode):
|
||||
field -- i.e., from Form.clean(). Returns an empty ErrorList if there
|
||||
are none.
|
||||
"""
|
||||
return self.errors.get(NON_FIELD_ERRORS, ErrorList())
|
||||
return self.errors.get(NON_FIELD_ERRORS, self.error_class())
|
||||
|
||||
def full_clean(self):
|
||||
"""
|
||||
@ -241,7 +243,7 @@ class BoundField(StrAndUnicode):
|
||||
Returns an ErrorList for this field. Returns an empty ErrorList
|
||||
if there are none.
|
||||
"""
|
||||
return self.form.errors.get(self.name, ErrorList())
|
||||
return self.form.errors.get(self.name, self.form.error_class())
|
||||
errors = property(_errors)
|
||||
|
||||
def as_widget(self, widget=None, attrs=None):
|
||||
|
@ -30,6 +30,7 @@ class CycleNode(Node):
|
||||
def render(self, context):
|
||||
self.counter += 1
|
||||
value = self.cyclevars[self.counter % self.cyclevars_len]
|
||||
value = resolve_variable(value, context)
|
||||
if self.variable_name:
|
||||
context[self.variable_name] = value
|
||||
return value
|
||||
@ -403,7 +404,7 @@ def cycle(parser, token):
|
||||
the loop::
|
||||
|
||||
{% for o in some_list %}
|
||||
<tr class="{% cycle row1,row2 %}">
|
||||
<tr class="{% cycle 'row1' 'row2' %}">
|
||||
...
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@ -411,16 +412,17 @@ def cycle(parser, token):
|
||||
Outside of a loop, give the values a unique name the first time you call
|
||||
it, then use that name each sucessive time through::
|
||||
|
||||
<tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle 'row1' 'row2' 'row3' as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
|
||||
You can use any number of values, seperated by commas. Make sure not to
|
||||
put spaces between the values -- only commas.
|
||||
You can use any number of values, seperated by spaces. Commas can also
|
||||
be used to separate values; if a comma is used, the cycle values are
|
||||
interpreted as literal strings.
|
||||
"""
|
||||
|
||||
# Note: This returns the exact same node on each {% cycle name %} call; that
|
||||
# is, the node object returned from {% cycle a,b,c as name %} and the one
|
||||
# is, the node object returned from {% cycle a b c as name %} and the one
|
||||
# returned from {% cycle name %} are the exact same object. This shouldn't
|
||||
# cause problems (heh), but if it does, now you know.
|
||||
#
|
||||
@ -429,40 +431,34 @@ def cycle(parser, token):
|
||||
# a global variable, which would make cycle names have to be unique across
|
||||
# *all* templates.
|
||||
|
||||
args = token.contents.split()
|
||||
args = token.split_contents()
|
||||
|
||||
if len(args) < 2:
|
||||
raise TemplateSyntaxError("'Cycle' statement requires at least two arguments")
|
||||
raise TemplateSyntaxError("'cycle' tag requires at least two arguments")
|
||||
|
||||
elif len(args) == 2 and "," in args[1]:
|
||||
# {% cycle a,b,c %}
|
||||
cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks
|
||||
return CycleNode(cyclevars)
|
||||
# {% cycle name %}
|
||||
if ',' in args[1]:
|
||||
# Backwards compatibility: {% cycle a,b %} or {% cycle a,b as foo %}
|
||||
# case.
|
||||
args[1:2] = ['"%s"' % arg for arg in args[1].split(",")]
|
||||
|
||||
elif len(args) == 2:
|
||||
if len(args) == 2:
|
||||
# {% cycle foo %} case
|
||||
name = args[1]
|
||||
if not hasattr(parser, '_namedCycleNodes'):
|
||||
raise TemplateSyntaxError("No named cycles in template: '%s' is not defined" % name)
|
||||
if name not in parser._namedCycleNodes:
|
||||
if not name in parser._namedCycleNodes:
|
||||
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
||||
return parser._namedCycleNodes[name]
|
||||
|
||||
elif len(args) == 4:
|
||||
# {% cycle a,b,c as name %}
|
||||
if args[2] != 'as':
|
||||
raise TemplateSyntaxError("Second 'cycle' argument must be 'as'")
|
||||
cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks
|
||||
name = args[3]
|
||||
node = CycleNode(cyclevars, name)
|
||||
|
||||
if len(args) > 4 and args[-2] == 'as':
|
||||
name = args[-1]
|
||||
node = CycleNode(args[1:-2], name)
|
||||
if not hasattr(parser, '_namedCycleNodes'):
|
||||
parser._namedCycleNodes = {}
|
||||
|
||||
parser._namedCycleNodes[name] = node
|
||||
return node
|
||||
|
||||
else:
|
||||
raise TemplateSyntaxError("Invalid arguments to 'cycle': %s" % args)
|
||||
node = CycleNode(args[1:])
|
||||
return node
|
||||
cycle = register.tag(cycle)
|
||||
|
||||
def debug(parser, token):
|
||||
|
@ -39,6 +39,8 @@ def object_list(request, queryset, paginate_by=None, page=None,
|
||||
first_on_page
|
||||
the result number of the first object in the
|
||||
object_list (1-indexed)
|
||||
page_range:
|
||||
A list of the page numbers (1-indexed).
|
||||
"""
|
||||
if extra_context is None: extra_context = {}
|
||||
queryset = queryset._clone()
|
||||
@ -47,10 +49,17 @@ def object_list(request, queryset, paginate_by=None, page=None,
|
||||
if not page:
|
||||
page = request.GET.get('page', 1)
|
||||
try:
|
||||
page = int(page)
|
||||
object_list = paginator.get_page(page - 1)
|
||||
except (InvalidPage, ValueError):
|
||||
if page == 1 and allow_empty:
|
||||
page_number = int(page)
|
||||
except ValueError:
|
||||
if page == 'last':
|
||||
page_number = paginator.pages
|
||||
else:
|
||||
# Page is not 'last', nor can it be converted to an int
|
||||
raise Http404
|
||||
try:
|
||||
object_list = paginator.get_page(page_number - 1)
|
||||
except InvalidPage:
|
||||
if page_number == 1 and allow_empty:
|
||||
object_list = []
|
||||
else:
|
||||
raise Http404
|
||||
@ -58,15 +67,16 @@ def object_list(request, queryset, paginate_by=None, page=None,
|
||||
'%s_list' % template_object_name: object_list,
|
||||
'is_paginated': paginator.pages > 1,
|
||||
'results_per_page': paginate_by,
|
||||
'has_next': paginator.has_next_page(page - 1),
|
||||
'has_previous': paginator.has_previous_page(page - 1),
|
||||
'page': page,
|
||||
'next': page + 1,
|
||||
'previous': page - 1,
|
||||
'last_on_page': paginator.last_on_page(page - 1),
|
||||
'first_on_page': paginator.first_on_page(page - 1),
|
||||
'has_next': paginator.has_next_page(page_number - 1),
|
||||
'has_previous': paginator.has_previous_page(page_number - 1),
|
||||
'page': page_number,
|
||||
'next': page_number + 1,
|
||||
'previous': page_number - 1,
|
||||
'last_on_page': paginator.last_on_page(page_number - 1),
|
||||
'first_on_page': paginator.first_on_page(page_number - 1),
|
||||
'pages': paginator.pages,
|
||||
'hits' : paginator.hits,
|
||||
'page_range' : paginator.page_range
|
||||
}, context_processors)
|
||||
else:
|
||||
c = RequestContext(request, {
|
||||
|
@ -688,9 +688,8 @@ A page representing a list of objects.
|
||||
* ``paginate_by``: An integer specifying how many objects should be
|
||||
displayed per page. If this is given, the view will paginate objects with
|
||||
``paginate_by`` objects per page. The view will expect either a ``page``
|
||||
query string parameter (via ``GET``) containing a 1-based page
|
||||
number, or a ``page`` variable specified in the URLconf. See
|
||||
"Notes on pagination" below.
|
||||
query string parameter (via ``GET``) or a ``page`` variable specified in
|
||||
the URLconf. See "Notes on pagination" below.
|
||||
|
||||
* ``template_name``: The full name of a template to use in rendering the
|
||||
page. This lets you override the default template name (see below).
|
||||
@ -765,6 +764,9 @@ If the results are paginated, the context will contain these extra variables:
|
||||
* ``hits``: The total number of objects across *all* pages, not just this
|
||||
page.
|
||||
|
||||
* ``page_range``: A list of the page numbers that are available. This
|
||||
is 1-based.
|
||||
|
||||
Notes on pagination
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -777,12 +779,25 @@ specify the page number in the URL in one of two ways:
|
||||
(r'^objects/page(?P<page>[0-9]+)/$', 'object_list', dict(info_dict))
|
||||
|
||||
* Pass the page number via the ``page`` query-string parameter. For
|
||||
example, a URL would look like this:
|
||||
example, a URL would look like this::
|
||||
|
||||
/objects/?page=3
|
||||
|
||||
In both cases, ``page`` is 1-based, not 0-based, so the first page would be
|
||||
represented as page ``1``.
|
||||
* To loop over all the available page numbers, use the ``page_range``
|
||||
variable. You can iterate over the list provided by ``page_range``
|
||||
to create a link to every page of results.
|
||||
|
||||
These values and lists are is 1-based, not 0-based, so the first page would be
|
||||
represented as page ``1``. As a special case, you are also permitted to use
|
||||
``last`` as a value for ``page``::
|
||||
|
||||
/objects/?page=last
|
||||
|
||||
This allows you to access the final page of results without first having to
|
||||
determine how many pages there are.
|
||||
|
||||
Note that ``page`` *must* be either a valid page number or the value ``last``;
|
||||
any other value for ``page`` will result in a 404 error.
|
||||
|
||||
``django.views.generic.list_detail.object_detail``
|
||||
--------------------------------------------------
|
||||
|
@ -554,6 +554,29 @@ method you're using::
|
||||
<p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
|
||||
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
|
||||
|
||||
Customizing the error list format
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, forms use ``django.newforms.util.ErrorList`` to format validation
|
||||
errors. If you'd like to use an alternate class for displaying errors, you can
|
||||
pass that in at construction time::
|
||||
|
||||
>>> from django.newforms.util import ErrorList
|
||||
>>> class DivErrorList(ErrorList):
|
||||
... def __unicode__(self):
|
||||
... return self.as_divs()
|
||||
... def as_divs(self):
|
||||
... if not self: return u''
|
||||
... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
|
||||
>>> f = ContactForm(data, auto_id=False, error_class=DivErrorList)
|
||||
>>> f.as_p()
|
||||
<div class="errorlist"><div class="error">This field is required.</div></div>
|
||||
<p>Subject: <input type="text" name="subject" maxlength="100" /></p>
|
||||
<p>Message: <input type="text" name="message" value="Hi there" /></p>
|
||||
<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div>
|
||||
<p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
|
||||
<p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
|
||||
|
||||
More granular output
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -1893,6 +1916,17 @@ Note that your callback needs to handle *all* possible model field types, not
|
||||
just the ones that you want to behave differently to the default. That's why
|
||||
this example has an ``else`` clause that implements the default behavior.
|
||||
|
||||
.. warning::
|
||||
The field that is passed into the ``formfield_callback`` function in
|
||||
``form_for_model()`` and ``form_for_instance`` is the field instance from
|
||||
your model's class. You **must not** alter that object at all; treat it
|
||||
as read-only!
|
||||
|
||||
If you make any alterations to that object, it will affect any future
|
||||
users of the model class, because you will have changed the field object
|
||||
used to construct the class. This is almost certainly what you don't want
|
||||
to have happen.
|
||||
|
||||
Finding the model associated with a form
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -183,6 +183,9 @@ subclass of dictionary. Exceptions are outlined here:
|
||||
|
||||
* ``__getitem__(key)`` -- Returns the value for the given key. If the key
|
||||
has more than one value, ``__getitem__()`` returns the last value.
|
||||
Raises ``django.utils.datastructure.MultiValueDictKeyError`` if the key
|
||||
does not exist (fortunately, this is a subclass of Python's standard
|
||||
``KeyError``, so you can stick to catching ``KeyError``).
|
||||
|
||||
* ``__setitem__(key, value)`` -- Sets the given key to ``[value]``
|
||||
(a Python list whose single element is ``value``). Note that this, as
|
||||
|
@ -316,6 +316,9 @@ Here's how Django uses the sites framework:
|
||||
* The shortcut view (``django.views.defaults.shortcut``) uses the domain of
|
||||
the current ``Site`` object when calculating an object's URL.
|
||||
|
||||
* In the admin framework, the ''view on site'' link uses the current
|
||||
``Site`` to work out the domain for the site that it will redirect to.
|
||||
|
||||
.. _redirects framework: ../redirects/
|
||||
.. _flatpages framework: ../flatpages/
|
||||
.. _syndication framework: ../syndication_feeds/
|
||||
|
@ -366,25 +366,36 @@ Ignore everything between ``{% comment %}`` and ``{% endcomment %}``
|
||||
cycle
|
||||
~~~~~
|
||||
|
||||
Cycle among the given strings each time this tag is encountered.
|
||||
**Changed in Django development version**
|
||||
Cycle among the given strings or variables each time this tag is encountered.
|
||||
|
||||
Within a loop, cycles among the given strings each time through the loop::
|
||||
Within a loop, cycles among the given strings/variables each time through the
|
||||
loop::
|
||||
|
||||
{% for o in some_list %}
|
||||
<tr class="{% cycle row1,row2 %}">
|
||||
<tr class="{% cycle 'row1' 'row2' rowvar %}">
|
||||
...
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
Outside of a loop, give the values a unique name the first time you call it,
|
||||
then use that name each successive time through::
|
||||
|
||||
<tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle 'row1' 'row2' rowvar as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
|
||||
You can use any number of values, separated by commas. Make sure not to put
|
||||
spaces between the values -- only commas.
|
||||
You can use any number of values, separated by spaces. Values enclosed in
|
||||
single (') or double quotes (") are treated as string literals, while values
|
||||
without quotes are assumed to refer to context variables.
|
||||
|
||||
You can also separate values with commas::
|
||||
|
||||
{% cycle row1,row2,row3 %}
|
||||
|
||||
In this syntax, each value will be interpreted as literal text. The
|
||||
comma-based syntax exists for backwards-compatibility, and should not be
|
||||
used for new projects.
|
||||
|
||||
debug
|
||||
~~~~~
|
||||
|
@ -642,7 +642,23 @@ your function. Example::
|
||||
"Converts a string into all lowercase"
|
||||
return value.lower()
|
||||
|
||||
When you've written your filter definition, you need to register it with
|
||||
Template filters which expect strings
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you're writing a template filter which only expects a string as the first
|
||||
argument, you should use the included decorator ``stringfilter``. This will
|
||||
convert an object to it's string value before being passed to your function::
|
||||
|
||||
from django.template.defaultfilters import stringfilter
|
||||
|
||||
@stringfilter
|
||||
def lower(value):
|
||||
return value.lower()
|
||||
|
||||
Registering a custom filters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once you've written your filter definition, you need to register it with
|
||||
your ``Library`` instance, to make it available to Django's template language::
|
||||
|
||||
register.filter('cut', cut)
|
||||
@ -658,28 +674,18 @@ If you're using Python 2.4 or above, you can use ``register.filter()`` as a
|
||||
decorator instead::
|
||||
|
||||
@register.filter(name='cut')
|
||||
@stringfilter
|
||||
def cut(value, arg):
|
||||
return value.replace(arg, '')
|
||||
|
||||
@register.filter
|
||||
@stringfilter
|
||||
def lower(value):
|
||||
return value.lower()
|
||||
|
||||
If you leave off the ``name`` argument, as in the second example above, Django
|
||||
will use the function's name as the filter name.
|
||||
|
||||
Template filters which expect strings
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If you are writing a template filter which only expects a string as the first
|
||||
argument, you should use the included decorator ``stringfilter`` which will convert
|
||||
an object to it's string value before being passed to your function::
|
||||
|
||||
from django.template.defaultfilters import stringfilter
|
||||
|
||||
@stringfilter
|
||||
def lower(value):
|
||||
return value.lower()
|
||||
|
||||
Writing custom template tags
|
||||
----------------------------
|
||||
|
||||
|
@ -569,8 +569,8 @@ Testing responses
|
||||
|
||||
The ``get()`` and ``post()`` methods both return a ``Response`` object. This
|
||||
``Response`` object is *not* the same as the ``HttpResponse`` object returned
|
||||
Django views; this object is simpler and has some additional data useful for
|
||||
tests.
|
||||
Django views; the test response object has some additional data useful for
|
||||
test code to verify.
|
||||
|
||||
Specifically, a ``Response`` object has the following attributes:
|
||||
|
||||
@ -582,7 +582,7 @@ Specifically, a ``Response`` object has the following attributes:
|
||||
|
||||
``content`` The body of the response, as a string. This is the final
|
||||
page content as rendered by the view, or any error
|
||||
message (such as the URL for a 302 redirect).
|
||||
message.
|
||||
|
||||
``context`` The template ``Context`` instance that was used to render
|
||||
the template that produced the response content.
|
||||
@ -591,6 +591,8 @@ Specifically, a ``Response`` object has the following attributes:
|
||||
``context`` will be a list of ``Context``
|
||||
objects, in the order in which they were rendered.
|
||||
|
||||
``headers`` The HTTP headers of the response. This is a dictionary.
|
||||
|
||||
``request`` The request data that stimulated the response.
|
||||
|
||||
``status_code`` The HTTP status of the response, as an integer. See
|
||||
|
@ -77,4 +77,8 @@ True
|
||||
>>> paginator = ObjectPaginator(Article.objects.all(), 10, orphans=1)
|
||||
>>> paginator.pages
|
||||
2
|
||||
|
||||
# The paginator can provide a list of all available pages
|
||||
>>> paginator.page_range
|
||||
[1, 2]
|
||||
"""}
|
||||
|
@ -1514,4 +1514,294 @@ ValidationError: [u'Enter a valid SoFi number']
|
||||
>>> s = NLProvinceSelect()
|
||||
>>> s.render('provinces', 'OV')
|
||||
u'<select name="provinces">\n<option value="DR">Drente</option>\n<option value="FL">Flevoland</option>\n<option value="FR">Friesland</option>\n<option value="GL">Gelderland</option>\n<option value="GR">Groningen</option>\n<option value="LB">Limburg</option>\n<option value="NB">Noord-Brabant</option>\n<option value="NH">Noord-Holland</option>\n<option value="OV" selected="selected">Overijssel</option>\n<option value="UT">Utrecht</option>\n<option value="ZE">Zeeland</option>\n<option value="ZH">Zuid-Holland</option>\n</select>'
|
||||
|
||||
# ARProvinceField #############################################################
|
||||
|
||||
>>> from django.contrib.localflavor.ar.forms import ARProvinceSelect
|
||||
>>> f = ARProvinceSelect()
|
||||
>>> f.render('provincias', 'A')
|
||||
u'<select name="provincias">\n<option value="B">Buenos Aires</option>\n<option value="K">Catamarca</option>\n<option value="H">Chaco</option>\n<option value="U">Chubut</option>\n<option value="C">Ciudad Aut\xf3noma de Buenos Aires</option>\n<option value="X">C\xf3rdoba</option>\n<option value="W">Corrientes</option>\n<option value="E">Entre R\xedos</option>\n<option value="P">Formosa</option>\n<option value="Y">Jujuy</option>\n<option value="L">La Pampa</option>\n<option value="F">La Rioja</option>\n<option value="M">Mendoza</option>\n<option value="N">Misiones</option>\n<option value="Q">Neuqu\xe9n</option>\n<option value="R">R\xedo Negro</option>\n<option value="A" selected="selected">Salta</option>\n<option value="J">San Juan</option>\n<option value="D">San Luis</option>\n<option value="Z">Santa Cruz</option>\n<option value="S">Santa Fe</option>\n<option value="G">Santiago del Estero</option>\n<option value="V">Tierra del Fuego, Ant\xe1rtida e Islas del Atl\xe1ntico Sur</option>\n<option value="T">Tucum\xe1n</option>\n</select>'
|
||||
|
||||
# ARPostalCodeField ###########################################################
|
||||
|
||||
>>> from django.contrib.localflavor.ar.forms import ARPostalCodeField
|
||||
>>> f = ARPostalCodeField()
|
||||
>>> f.clean('5000')
|
||||
u'5000'
|
||||
>>> f.clean('C1064AAB')
|
||||
u'C1064AAB'
|
||||
>>> f.clean('c1064AAB')
|
||||
u'C1064AAB'
|
||||
>>> f.clean('C1064aab')
|
||||
u'C1064AAB'
|
||||
>>> f.clean(u'4400')
|
||||
u'4400'
|
||||
>>> f.clean(u'C1064AAB')
|
||||
u'C1064AAB'
|
||||
>>> f.clean('C1064AABB')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Ensure this value has at most 8 characters (it has 9).']
|
||||
>>> f.clean('C1064AA')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean('C106AAB')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean('106AAB')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean('500')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Ensure this value has at least 4 characters (it has 3).']
|
||||
>>> f.clean('5PPP')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean(None)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
>>> f.clean('')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
>>> f.clean(u'')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
|
||||
>>> f = ARPostalCodeField(required=False)
|
||||
>>> f.clean('5000')
|
||||
u'5000'
|
||||
>>> f.clean('C1064AAB')
|
||||
u'C1064AAB'
|
||||
>>> f.clean('c1064AAB')
|
||||
u'C1064AAB'
|
||||
>>> f.clean('C1064aab')
|
||||
u'C1064AAB'
|
||||
>>> f.clean(u'4400')
|
||||
u'4400'
|
||||
>>> f.clean(u'C1064AAB')
|
||||
u'C1064AAB'
|
||||
>>> f.clean('C1064AABB')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Ensure this value has at most 8 characters (it has 9).']
|
||||
>>> f.clean('C1064AA')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean('C106AAB')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean('106AAB')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean('500')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Ensure this value has at least 4 characters (it has 3).']
|
||||
>>> f.clean('5PPP')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
|
||||
>>> f.clean(None)
|
||||
u''
|
||||
>>> f.clean('')
|
||||
u''
|
||||
>>> f.clean(u'')
|
||||
u''
|
||||
|
||||
# ARDNIField ##################################################################
|
||||
|
||||
>>> from django.contrib.localflavor.ar.forms import ARDNIField
|
||||
>>> f = ARDNIField()
|
||||
>>> f.clean('20123456')
|
||||
u'20123456'
|
||||
>>> f.clean('20.123.456')
|
||||
u'20123456'
|
||||
>>> f.clean('9123456')
|
||||
u'9123456'
|
||||
>>> f.clean('9.123.456')
|
||||
u'9123456'
|
||||
>>> f.clean(u'20123456')
|
||||
u'20123456'
|
||||
>>> f.clean(u'20.123.456')
|
||||
u'20123456'
|
||||
>>> f.clean('20.123456')
|
||||
u'20123456'
|
||||
>>> f.clean('101234566')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field requires 7 or 8 digits.']
|
||||
>>> f.clean('W0123456')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field requires only numbers.']
|
||||
>>> f.clean('10,123,456')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field requires only numbers.']
|
||||
>>> f.clean(None)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
>>> f.clean('')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
>>> f.clean(u'')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
|
||||
>>> f = ARDNIField(required=False)
|
||||
>>> f.clean('20123456')
|
||||
u'20123456'
|
||||
>>> f.clean('20.123.456')
|
||||
u'20123456'
|
||||
>>> f.clean('9123456')
|
||||
u'9123456'
|
||||
>>> f.clean('9.123.456')
|
||||
u'9123456'
|
||||
>>> f.clean(u'20123456')
|
||||
u'20123456'
|
||||
>>> f.clean(u'20.123.456')
|
||||
u'20123456'
|
||||
>>> f.clean('20.123456')
|
||||
u'20123456'
|
||||
>>> f.clean('101234566')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field requires 7 or 8 digits.']
|
||||
>>> f.clean('W0123456')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field requires only numbers.']
|
||||
>>> f.clean('10,123,456')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field requires only numbers.']
|
||||
>>> f.clean(None)
|
||||
u''
|
||||
>>> f.clean('')
|
||||
u''
|
||||
>>> f.clean(u'')
|
||||
u''
|
||||
|
||||
# ARCUITField #################################################################
|
||||
|
||||
>>> from django.contrib.localflavor.ar.forms import ARCUITField
|
||||
>>> f = ARCUITField()
|
||||
>>> f.clean('20-10123456-9')
|
||||
u'20-10123456-9'
|
||||
>>> f.clean(u'20-10123456-9')
|
||||
u'20-10123456-9'
|
||||
>>> f.clean('27-10345678-4')
|
||||
u'27-10345678-4'
|
||||
>>> f.clean('20101234569')
|
||||
u'20-10123456-9'
|
||||
>>> f.clean('27103456784')
|
||||
u'27-10345678-4'
|
||||
>>> f.clean('2-10123456-9')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('210123456-9')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('20-10123456')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('20-10123456-')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('20-10123456-5')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Invalid CUIT.']
|
||||
>>> f.clean(u'2-10123456-9')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('27-10345678-1')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Invalid CUIT.']
|
||||
>>> f.clean(u'27-10345678-1')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Invalid CUIT.']
|
||||
>>> f.clean(None)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
>>> f.clean('')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
>>> f.clean(u'')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
|
||||
>>> f = ARCUITField(required=False)
|
||||
>>> f.clean('20-10123456-9')
|
||||
u'20-10123456-9'
|
||||
>>> f.clean(u'20-10123456-9')
|
||||
u'20-10123456-9'
|
||||
>>> f.clean('27-10345678-4')
|
||||
u'27-10345678-4'
|
||||
>>> f.clean('20101234569')
|
||||
u'20-10123456-9'
|
||||
>>> f.clean('27103456784')
|
||||
u'27-10345678-4'
|
||||
>>> f.clean('2-10123456-9')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('210123456-9')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('20-10123456')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('20-10123456-')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('20-10123456-5')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Invalid CUIT.']
|
||||
>>> f.clean(u'2-10123456-9')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
|
||||
>>> f.clean('27-10345678-1')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Invalid CUIT.']
|
||||
>>> f.clean(u'27-10345678-1')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'Invalid CUIT.']
|
||||
>>> f.clean(None)
|
||||
u''
|
||||
>>> f.clean('')
|
||||
u''
|
||||
>>> f.clean(u'')
|
||||
u''
|
||||
"""
|
||||
|
@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from localflavor import localflavor_tests
|
||||
from regressions import regression_tests
|
||||
from util import util_tests
|
||||
|
||||
form_tests = r"""
|
||||
>>> from django.newforms import *
|
||||
@ -1606,10 +1607,18 @@ ValidationError: [u'This field is required.']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValidationError: [u'This field is required.']
|
||||
>>> f.clean('http://localhost')
|
||||
u'http://localhost'
|
||||
>>> f.clean('http://example.com')
|
||||
u'http://example.com'
|
||||
>>> f.clean('http://www.example.com')
|
||||
u'http://www.example.com'
|
||||
>>> f.clean('http://www.example.com:8000/test')
|
||||
u'http://www.example.com:8000/test'
|
||||
>>> f.clean('http://200.8.9.10')
|
||||
u'http://200.8.9.10'
|
||||
>>> f.clean('http://200.8.9.10:8000/test')
|
||||
u'http://200.8.9.10:8000/test'
|
||||
>>> f.clean('foo')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
@ -3794,14 +3803,6 @@ u'1'
|
||||
>>> smart_unicode('foo')
|
||||
u'foo'
|
||||
|
||||
# flatatt tests
|
||||
>>> from django.newforms.util import flatatt
|
||||
>>> flatatt({'id': "header"})
|
||||
u' id="header"'
|
||||
>>> flatatt({'class': "news", 'title': "Read this"})
|
||||
u' class="news" title="Read this"'
|
||||
>>> flatatt({})
|
||||
u''
|
||||
|
||||
####################################
|
||||
# Test accessing errors in clean() #
|
||||
@ -3821,12 +3822,38 @@ u''
|
||||
True
|
||||
>>> f.cleaned_data['username']
|
||||
u'sirrobin'
|
||||
|
||||
#######################################
|
||||
# Test overriding ErrorList in a form #
|
||||
#######################################
|
||||
|
||||
>>> from django.newforms.util import ErrorList
|
||||
>>> class DivErrorList(ErrorList):
|
||||
... def __unicode__(self):
|
||||
... return self.as_divs()
|
||||
... def as_divs(self):
|
||||
... if not self: return u''
|
||||
... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
|
||||
>>> class CommentForm(Form):
|
||||
... name = CharField(max_length=50, required=False)
|
||||
... email = EmailField()
|
||||
... comment = CharField()
|
||||
>>> data = dict(email='invalid')
|
||||
>>> f = CommentForm(data, auto_id=False, error_class=DivErrorList)
|
||||
>>> print f.as_p()
|
||||
<p>Name: <input type="text" name="name" maxlength="50" /></p>
|
||||
<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div>
|
||||
<p>Email: <input type="text" name="email" value="invalid" /></p>
|
||||
<div class="errorlist"><div class="error">This field is required.</div></div>
|
||||
<p>Comment: <input type="text" name="comment" /></p>
|
||||
|
||||
"""
|
||||
|
||||
__test__ = {
|
||||
'form_tests': form_tests,
|
||||
'localflavor': localflavor_tests,
|
||||
'regressions': regression_tests,
|
||||
'util_tests': util_tests,
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
45
tests/regressiontests/forms/util.py
Normal file
45
tests/regressiontests/forms/util.py
Normal file
@ -0,0 +1,45 @@
|
||||
# coding: utf-8
|
||||
"""
|
||||
Tests for newforms/util.py module.
|
||||
"""
|
||||
|
||||
util_tests = r"""
|
||||
>>> from django.newforms.util import *
|
||||
>>> from django.utils.translation import ugettext_lazy
|
||||
|
||||
###########
|
||||
# flatatt #
|
||||
###########
|
||||
|
||||
>>> from django.newforms.util import flatatt
|
||||
>>> flatatt({'id': "header"})
|
||||
u' id="header"'
|
||||
>>> flatatt({'class': "news", 'title': "Read this"})
|
||||
u' class="news" title="Read this"'
|
||||
>>> flatatt({})
|
||||
u''
|
||||
|
||||
###################
|
||||
# ValidationError #
|
||||
###################
|
||||
|
||||
# Can take a string.
|
||||
>>> print ValidationError("There was an error.").messages
|
||||
<ul class="errorlist"><li>There was an error.</li></ul>
|
||||
|
||||
# Can take a unicode string.
|
||||
>>> print ValidationError(u"Not \u03C0.").messages
|
||||
<ul class="errorlist"><li>Not π.</li></ul>
|
||||
|
||||
# Can take a lazy string.
|
||||
>>> print ValidationError(ugettext_lazy("Error.")).messages
|
||||
<ul class="errorlist"><li>Error.</li></ul>
|
||||
|
||||
# Can take a list.
|
||||
>>> print ValidationError(["Error one.", "Error two."]).messages
|
||||
<ul class="errorlist"><li>Error one.</li><li>Error two.</li></ul>
|
||||
|
||||
# Can take a mixture in a list.
|
||||
>>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages
|
||||
<ul class="errorlist"><li>First error.</li><li>Not π.</li><li>Error.</li></ul>
|
||||
"""
|
@ -306,6 +306,14 @@ class Templates(unittest.TestCase):
|
||||
'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError),
|
||||
'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
|
||||
'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
|
||||
'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
||||
# New format:
|
||||
'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),
|
||||
'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),
|
||||
'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),
|
||||
'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
||||
'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
|
||||
'cycle13': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),
|
||||
|
||||
### EXCEPTIONS ############################################################
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user