1
0
mirror of https://github.com/django/django.git synced 2025-07-04 01:39:20 +00:00

boulder-oracle-sprint: Merged to [5134]

git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@5135 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Boulder Sprinters 2007-05-01 15:33:10 +00:00
parent 5a7802586d
commit 90740c93e6
14 changed files with 231 additions and 44 deletions

View File

@ -181,6 +181,7 @@ answer newbie questions, and generally made Django that much better:
Luke Plant <http://lukeplant.me.uk/>
plisk
Daniel Poelzleithner <http://poelzi.org/>
polpak@yahoo.com
J. Rademaker
Michael Radziej <mir@noris.de>
ramiro
@ -224,6 +225,7 @@ answer newbie questions, and generally made Django that much better:
wam-djangobug@wamber.net
Dan Watson <http://theidioteque.net/>
Chris Wesseling <Chris.Wesseling@cwi.nl>
charly.wilhelm@gmail.com
Rachel Willmer <http://www.willmer.com/kb/>
Gary Wilson <gary.wilson@gmail.com>
wojtek

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*
from django.utils.translation import gettext_lazy as _
STATE_CHOICES = (
('AG', _('Aargau')),
('AI', _('Appenzell Innerrhoden')),
('AR', _('Appenzell Ausserrhoden')),
('BS', _('Basel-Stadt')),
('BL', _('Basel-Land')),
('BE', _('Berne')),
('FR', _('Fribourg')),
('GE', _('Geneva')),
('GL', _('Glarus')),
('GR', _('Graubuenden')),
('JU', _('Jura')),
('LU', _('Lucerne')),
('NE', _('Neuchatel')),
('NW', _('Nidwalden')),
('OW', _('Obwalden')),
('SH', _('Schaffhausen')),
('SZ', _('Schwyz')),
('SO', _('Solothurn')),
('SG', _('St. Gallen')),
('TG', _('Thurgau')),
('TI', _('Ticino')),
('UR', _('Uri')),
('VS', _('Valais')),
('VD', _('Vaud')),
('ZG', _('Zug')),
('ZH', _('Zurich'))
)

View File

@ -0,0 +1,109 @@
"""
Swiss-specific Form helpers
"""
from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.utils.encoding import smart_unicode
from django.utils.translation import gettext
import re
id_re = re.compile(r"^(?P<idnumber>\w{8})(?P<pos9>(\d{1}|<))(?P<checksum>\d{1})$")
phone_digits_re = re.compile(r'^0([1-9]{1})\d{8}$')
class CHZipCodeField(RegexField):
def __init__(self, *args, **kwargs):
super(CHZipCodeField, self).__init__(r'^\d{4}$',
max_length=None, min_length=None,
error_message=gettext('Enter a zip code in the format XXXX.'),
*args, **kwargs)
class CHPhoneNumberField(Field):
"""
Validate local Swiss phone number (not international ones)
The correct format is '0XX XXX XX XX'.
'0XX.XXX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
'0XX XXX XX XX'.
"""
def clean(self, value):
super(CHPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
value = re.sub('(\.|\s|/|-)', '', smart_unicode(value))
m = phone_digits_re.search(value)
if m:
return u'%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10])
raise ValidationError('Phone numbers must be in 0XX XXX XX XX format.')
class CHStateSelect(Select):
"""
A Select widget that uses a list of CH states as its choices.
"""
def __init__(self, attrs=None):
from ch_states import STATE_CHOICES # relative import
super(CHStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
class CHIdentityCardNumberField(Field):
"""
A Swiss identity card number.
Checks the following rules to determine whether the number is valid:
* Conforms to the X1234567<0 or 1234567890 format.
* Included checksums match calculated checksums
Algorithm is documented at http://adi.kousz.ch/artikel/IDCHE.htm
"""
def has_valid_checksum(self, number):
given_number, given_checksum = number[:-1], number[-1]
new_number = given_number
calculated_checksum = 0
fragment = ""
parameter = 7
first = str(number[:1])
if first.isalpha():
num = ord(first.upper()) - 65
if num < 0 or num > 8:
return False
new_number = str(num) + new_number[1:]
new_number = new_number[:8] + '0'
if not new_number.isdigit():
return False
for i in range(len(new_number)):
fragment = int(new_number[i])*parameter
calculated_checksum += fragment
if parameter == 1:
parameter = 7
elif parameter == 3:
parameter = 1
elif parameter ==7:
parameter = 3
return str(calculated_checksum)[-1] == given_checksum
def clean(self, value):
super(CHIdentityCardNumberField, self).clean(value)
error_msg = gettext('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.')
if value in EMPTY_VALUES:
return u''
match = re.match(id_re, value)
if not match:
raise ValidationError(error_msg)
idnumber, pos9, checksum = match.groupdict()['idnumber'], match.groupdict()['pos9'], match.groupdict()['checksum']
if idnumber == '00000000' or \
idnumber == 'A0000000':
raise ValidationError(error_msg)
all_digits = "%s%s%s" % (idnumber, pos9, checksum)
if not self.has_valid_checksum(all_digits):
raise ValidationError(error_msg)
return u'%s%s%s' % (idnumber, pos9, checksum)

View File

@ -598,6 +598,7 @@ def syncdb(verbosity=1, interactive=True):
# Install custom SQL for the app (but only if this
# is a model we've just created)
for app in models.get_apps():
app_name = app.__name__.split('.')[-2]
for model in models.get_models(app):
if model in created_models:
custom_sql = get_custom_sql_for_model(model)

View File

@ -893,6 +893,12 @@ class USStateField(Field):
def get_manipulator_field_objs(self):
return [oldforms.USStateField]
def formfield(self, **kwargs):
from django.contrib.localflavor.us.forms import USStateSelect
defaults = {'widget': USStateSelect}
defaults.update(kwargs)
return super(USStateField, self).formfield(**defaults)
class XMLField(TextField):
def __init__(self, verbose_name=None, name=None, schema_path=None, **kwargs):
self.schema_path = schema_path

View File

@ -903,6 +903,13 @@ def find_field(name, field_list, related_query):
return None
return matches[0]
def field_choices(field_list, related_query):
if related_query:
choices = [f.field.related_query_name() for f in field_list]
else:
choices = [f.name for f in field_list]
return choices
def lookup_inner(path, lookup_type, value, opts, table, column):
qn = backend.quote_name
joins, where, params = SortedDict(), [], []
@ -987,7 +994,11 @@ def lookup_inner(path, lookup_type, value, opts, table, column):
except FieldFound: # Match found, loop has been shortcut.
pass
else: # No match found.
raise TypeError, "Cannot resolve keyword '%s' into field" % name
choices = field_choices(current_opts.many_to_many, False) + \
field_choices(current_opts.get_all_related_many_to_many_objects(), True) + \
field_choices(current_opts.get_all_related_objects(), True) + \
field_choices(current_opts.fields, False)
raise TypeError, "Cannot resolve keyword '%s' into field, choices are: %s" % (name, ", ".join(choices))
# Check whether an intermediate join is required between current_table
# and new_table.

View File

@ -500,44 +500,17 @@ in standard language format. For example, U.S. English is ``"en-us"``. See the
LANGUAGES
---------
Default: A tuple of all available languages. Currently, this is::
Default: A tuple of all available languages. This list is continually growing
and including a copy here would inevitably become rapidly out of date. You can
see the current list of translated languages by looking in
``django/conf/global_settings.py`` (or view the `online source`_).
LANGUAGES = (
('ar', _('Arabic')),
('bn', _('Bengali')),
('cs', _('Czech')),
('cy', _('Welsh')),
('da', _('Danish')),
('de', _('German')),
('el', _('Greek')),
('en', _('English')),
('es', _('Spanish')),
('es_AR', _('Argentinean Spanish')),
('fr', _('French')),
('gl', _('Galician')),
('hu', _('Hungarian')),
('he', _('Hebrew')),
('is', _('Icelandic')),
('it', _('Italian')),
('ja', _('Japanese')),
('nl', _('Dutch')),
('no', _('Norwegian')),
('pt-br', _('Brazilian')),
('ro', _('Romanian')),
('ru', _('Russian')),
('sk', _('Slovak')),
('sl', _('Slovenian')),
('sr', _('Serbian')),
('sv', _('Swedish')),
('ta', _('Tamil')),
('uk', _('Ukrainian')),
('zh-cn', _('Simplified Chinese')),
('zh-tw', _('Traditional Chinese')),
)
.. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py
A tuple of two-tuples in the format (language code, language name). This
specifies which languages are available for language selection. See the
`internationalization docs`_ for details.
The list is a tuple of two-tuples in the format (language code, language
name) -- for example, ``('ja', 'Japanese')``. This specifies which languages
are available for language selection. See the `internationalization docs`_ for
details.
Generally, the default value should suffice. Only set this setting if you want
to restrict language selection to a subset of the Django-provided languages.

View File

@ -71,7 +71,7 @@ __test__ = {'API_TESTS':"""
>>> Author.objects.filter(firstname__exact='John')
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'firstname' into field
TypeError: Cannot resolve keyword 'firstname' into field, choices are: article, id, first_name, last_name
>>> a = Author.objects.get(last_name__exact='Smith')
>>> a.first_name

View File

@ -223,11 +223,11 @@ DoesNotExist: Article matching query does not exist.
>>> Article.objects.filter(pub_date_year='2005').count()
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'pub_date_year' into field
TypeError: Cannot resolve keyword 'pub_date_year' into field, choices are: id, headline, pub_date
>>> Article.objects.filter(headline__starts='Article')
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'headline__starts' into field
TypeError: Cannot resolve keyword 'headline__starts' into field, choices are: id, headline, pub_date
"""}

View File

@ -174,13 +174,13 @@ False
>>> Article.objects.filter(reporter_id__exact=1)
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'reporter_id' into field
TypeError: Cannot resolve keyword 'reporter_id' into field, choices are: id, headline, pub_date, reporter
# You need to specify a comparison clause
>>> Article.objects.filter(reporter_id=1)
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'reporter_id' into field
TypeError: Cannot resolve keyword 'reporter_id' into field, choices are: id, headline, pub_date, reporter
# You can also instantiate an Article by passing
# the Reporter's ID instead of a Reporter object.

View File

@ -55,5 +55,5 @@ __test__ = {'API_TESTS':"""
>>> Poll.objects.get(choice__name__exact="This is the answer")
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'choice' into field
TypeError: Cannot resolve keyword 'choice' into field, choices are: poll_choice, related_choice, id, question, creator
"""}

View File

@ -1011,6 +1011,60 @@ Traceback (most recent call last):
...
ValidationError: [u'Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.']
# CHZipCodeField ############################################################
>>> from django.contrib.localflavor.ch.forms import CHZipCodeField
>>> f = CHZipCodeField()
>>> f.clean('800x')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXX.']
>>> f.clean('80 00')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXX.']
>>> f.clean('8000')
u'8000'
# CHPhoneNumberField ########################################################
>>> from django.contrib.localflavor.ch.forms import CHPhoneNumberField
>>> f = CHPhoneNumberField()
>>> f.clean('01234567890')
Traceback (most recent call last):
...
ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.']
>>> f.clean('1234567890')
Traceback (most recent call last):
...
ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.']
>>> f.clean('0123456789')
u'012 345 67 89'
# CHIdentityCardNumberField #################################################
>>> from django.contrib.localflavor.ch.forms import CHIdentityCardNumberField
>>> f = CHIdentityCardNumberField()
>>> f.clean('C1234567<0')
u'C1234567<0'
>>> f.clean('C1234567<1')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.']
>>> f.clean('2123456700')
u'2123456700'
>>> f.clean('2123456701')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.']
# CHStateSelect #############################################################
>>> from django.contrib.localflavor.ch.forms import CHStateSelect
>>> w = CHStateSelect()
>>> w.render('state', 'AG')
u'<select name="state">\n<option value="AG" selected="selected">Aargau</option>\n<option value="AI">Appenzell Innerrhoden</option>\n<option value="AR">Appenzell Ausserrhoden</option>\n<option value="BS">Basel-Stadt</option>\n<option value="BL">Basel-Land</option>\n<option value="BE">Berne</option>\n<option value="FR">Fribourg</option>\n<option value="GE">Geneva</option>\n<option value="GL">Glarus</option>\n<option value="GR">Graubuenden</option>\n<option value="JU">Jura</option>\n<option value="LU">Lucerne</option>\n<option value="NE">Neuchatel</option>\n<option value="NW">Nidwalden</option>\n<option value="OW">Obwalden</option>\n<option value="SH">Schaffhausen</option>\n<option value="SZ">Schwyz</option>\n<option value="SO">Solothurn</option>\n<option value="SG">St. Gallen</option>\n<option value="TG">Thurgau</option>\n<option value="TI">Ticino</option>\n<option value="UR">Uri</option>\n<option value="VS">Valais</option>\n<option value="VD">Vaud</option>\n<option value="ZG">Zug</option>\n<option value="ZH">Zurich</option>\n</select>'
## AUPostCodeField ##########################################################
A field that accepts a four digit Australian post code.

View File

@ -32,7 +32,7 @@ __test__ = {'API_TESTS':"""
>>> Choice.objects.filter(foo__exact=None)
Traceback (most recent call last):
...
TypeError: Cannot resolve keyword 'foo' into field
TypeError: Cannot resolve keyword 'foo' into field, choices are: id, poll, choice
# Can't use None on anything other than __exact
>>> Choice.objects.filter(id__gt=None)