Permalink
Browse files

schema-evolution: updated from trunk/HEAD (r5787)

git-svn-id: http://code.djangoproject.com/svn/django/branches/schema-evolution@5788 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent fd77e42 commit 0f5a5a0594597dd10afe187e0ae8cecf11f5848b @keredson keredson committed Aug 2, 2007
Showing with 580 additions and 158 deletions.
  1. +3 −1 AUTHORS
  2. +16 −3 django/contrib/auth/models.py
  3. +19 −0 django/contrib/auth/tests.py
  4. +2 −1 django/contrib/databrowse/plugins/fieldchoices.py
  5. +1 −1 django/contrib/databrowse/templates/databrowse/calendar_day.html
  6. +1 −1 django/contrib/databrowse/templates/databrowse/calendar_month.html
  7. +1 −1 django/contrib/databrowse/templates/databrowse/choice_detail.html
  8. +1 −1 django/contrib/databrowse/templates/databrowse/choice_list.html
  9. +1 −1 django/contrib/databrowse/templates/databrowse/homepage.html
  10. +1 −1 django/contrib/databrowse/templates/databrowse/model_detail.html
  11. +5 −5 django/contrib/databrowse/templates/databrowse/object_detail.html
  12. +12 −11 django/core/management.py
  13. +2 −1 django/db/models/fields/__init__.py
  14. +0 −4 django/db/models/manager.py
  15. +17 −9 django/db/models/query.py
  16. +10 −11 django/newforms/forms.py
  17. +27 −6 django/newforms/widgets.py
  18. +45 −15 django/shortcuts/__init__.py
  19. +15 −4 django/template/loaders/app_directories.py
  20. +9 −3 django/template/loaders/filesystem.py
  21. +1 −1 django/test/client.py
  22. +81 −33 django/test/simple.py
  23. +1 −1 django/test/testcases.py
  24. +4 −0 django/test/utils.py
  25. +23 −0 django/utils/_os.py
  26. +5 −2 django/utils/http.py
  27. +19 −5 docs/authentication.txt
  28. +16 −0 docs/contributing.txt
  29. +12 −4 docs/db-api.txt
  30. +38 −0 docs/model-api.txt
  31. +41 −7 docs/testing.txt
  32. +24 −3 tests/modeltests/get_object_or_404/models.py
  33. +16 −8 tests/modeltests/lookup/models.py
  34. +12 −0 tests/modeltests/test_client/models.py
  35. +1 −2 tests/modeltests/test_client/views.py
  36. +15 −3 tests/regressiontests/forms/tests.py
  37. 0 tests/regressiontests/model_fields/__init__.py
  38. 0 tests/regressiontests/model_fields/models.py
  39. +18 −0 tests/regressiontests/model_fields/tests.py
  40. +46 −2 tests/regressiontests/templates/tests.py
  41. +12 −1 tests/regressiontests/test_client_regress/models.py
  42. +7 −6 tests/runtests.py
View
@@ -117,7 +117,7 @@ answer newbie questions, and generally made Django that much better:
glin@seznam.cz
martin.glueck@gmail.com
GomoX <gomo@datafull.com>
- Mario Gonzalez <gonzalemario @t gmail.com>
+ Mario Gonzalez <gonzalemario@gmail.com>
Simon Greenhill <dev@simon.net.nz>
Owen Griffiths
Espen Grindhaug <http://grindhaug.org/>
@@ -214,6 +214,7 @@ answer newbie questions, and generally made Django that much better:
plisk
Daniel Poelzleithner <http://poelzi.org/>
polpak@yahoo.com
+ Johann Queuniet <johann.queuniet@adh.naellia.eu>
J. Rademaker
Michael Radziej <mir@noris.de>
Ramiro Morales <rm0@gmx.net>
@@ -242,6 +243,7 @@ answer newbie questions, and generally made Django that much better:
Thomas Steinacher <http://www.eggdrop.ch/>
nowell strite
Sundance
+ SuperJared
Radek Švarz <http://www.svarz.cz/translate/>
Swaroop C H <http://www.swaroopch.info>
Aaron Swartz <http://www.aaronsw.com/>
@@ -7,6 +7,8 @@
import datetime
import urllib
+UNUSABLE_PASSWORD = '!' # This will never be a valid hash
+
try:
set
except NameError:
@@ -83,11 +85,14 @@ def __unicode__(self):
return self.name
class UserManager(models.Manager):
- def create_user(self, username, email, password):
+ def create_user(self, username, email, password=None):
"Creates and saves a User with the given username, e-mail and password."
now = datetime.datetime.now()
user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
- user.set_password(password)
+ if password:
+ user.set_password(password)
+ else:
+ user.set_unusable_password()
user.save()
return user
@@ -179,6 +184,13 @@ def check_password(self, raw_password):
return is_correct
return check_password(raw_password, self.password)
+ def set_unusable_password(self):
+ # Sets a value that will never be a valid hash
+ self.password = UNUSABLE_PASSWORD
+
+ def has_usable_password(self):
+ return self.password != UNUSABLE_PASSWORD
+
def get_group_permissions(self):
"Returns a list of permission strings that this user has through his/her groups."
if not hasattr(self, '_group_perm_cache'):
@@ -268,7 +280,8 @@ def get_profile(self):
return self._profile_cache
class Message(models.Model):
- """The message system is a lightweight way to queue messages for given users. A message is associated with a User instance (so it is only applicable for registered users). There's no concept of expiration or timestamps. Messages are created by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message.
+ """
+ The message system is a lightweight way to queue messages for given users. A message is associated with a User instance (so it is only applicable for registered users). There's no concept of expiration or timestamps. Messages are created by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message.
"""
user = models.ForeignKey(User)
message = models.TextField(_('message'))
@@ -0,0 +1,19 @@
+"""
+>>> from models import User
+>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
+>>> u.has_usable_password()
+True
+>>> u.check_password('bad')
+False
+>>> u.check_password('testpw')
+True
+>>> u.set_unusable_password()
+>>> u.save()
+>>> u.check_password('testpw')
+False
+>>> u.has_usable_password()
+False
+>>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
+>>> u2.has_usable_password()
+False
+"""
@@ -37,9 +37,10 @@ def model_index_html(self, request, model, site):
def urls(self, plugin_name, easy_instance_field):
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
+ field_value = smart_str(easy_instance_field.raw_value)
return [u'%s%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
- urllib.quote(smart_str(easy_instance_field.raw_value)))]
+ urllib.quote(field_value, safe=''))]
def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site
@@ -10,7 +10,7 @@
<ul class="objectlist">
{% for object in object_list %}
-<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</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 object in object_list %}
-<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</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 object in object_list %}
-<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</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 }}</a></li>
+<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li>
{% endfor %}
</ul>
@@ -11,7 +11,7 @@
<h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2>
<p>
{% for object in model.sample_objects %}
- <a href="{{ object.url }}">{{ object }}</a>,
+ <a href="{{ object.url }}">{{ object|escape }}</a>,
{% endfor %}
<a class="more" href="{{ model.url }}">More &rarr;</a>
</p>
@@ -12,7 +12,7 @@
<ul class="objectlist">
{% for object in model.objects %}
- <li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
+ <li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>
@@ -4,18 +4,18 @@
{% block content %}
-<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object }}</div>
+<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object|escape }}</div>
-<h1>{{ object.model.verbose_name|capfirst }}: {{ object }}</h1>
+<h1>{{ object.model.verbose_name|capfirst }}: {{ object|escape }}</h1>
<table class="objectinfo">
{% for field in object.fields %}
<tr class="{% cycle odd,even %}">
<th>{{ field.field.verbose_name|capfirst }}</th>
<td>
{% if field.urls %}
-{% for urlvalue in field.urls %}
-{% if urlvalue.1 %}<a href="{{ urlvalue.1 }}">{% endif %}{{ urlvalue.0 }}{% if urlvalue.1 %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
+{% for value, url in field.urls %}
+{% if url %}<a href="{{ url }}">{% endif %}{{ value|escape }}{% if url %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
{% endfor %}
{% else %}None{% endif %}
</td>
@@ -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 }}</a></li>
+ <li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>
{% else %}
View
@@ -1454,7 +1454,8 @@ def inner_run():
except (AttributeError, KeyError):
error_text = str(e)
sys.stderr.write(style.ERROR("Error: %s" % error_text) + '\n')
- sys.exit(1)
+ # Need to use an OS exit because sys.exit doesn't work in a thread
+ os._exit(1)
except KeyboardInterrupt:
sys.exit(0)
if use_reloader:
@@ -1548,16 +1549,11 @@ def runfcgi(args):
runfastcgi(args)
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
-def test(app_labels, verbosity=1):
+def test(test_labels, verbosity=1, interactive=True):
"Runs the test suite for the specified applications"
from django.conf import settings
from django.db.models import get_app, get_apps
-
- if len(app_labels) == 0:
- app_list = get_apps()
- else:
- app_list = [get_app(app_label) for app_label in app_labels]
-
+
test_path = settings.TEST_RUNNER.split('.')
# Allow for Python 2.5 relative paths
if len(test_path) > 1:
@@ -1567,12 +1563,12 @@ def test(app_labels, verbosity=1):
test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1])
- failures = test_runner(app_list, verbosity)
+ failures = test_runner(test_labels, verbosity=verbosity, interactive=interactive)
if failures:
sys.exit(failures)
test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
-test.args = '[--verbosity] ' + APP_ARGS
+test.args = '[--verbosity] [--noinput]' + APP_ARGS
def load_data(fixture_labels, verbosity=1):
"Installs the provided fixture file(s) as data in the database."
@@ -1849,7 +1845,12 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
action_mapping[action](args[1])
except IndexError:
parser.print_usage_and_exit()
- elif action in ('test', 'loaddata'):
+ elif action == 'test':
+ try:
+ action_mapping[action](args[1:], int(options.verbosity), options.interactive)
+ except IndexError:
+ parser.print_usage_and_exit()
+ elif action == 'loaddata':
try:
action_mapping[action](args[1:], int(options.verbosity))
except IndexError:
@@ -621,7 +621,8 @@ def to_python(self, value):
try:
return decimal.Decimal(value)
except decimal.InvalidOperation:
- raise validators.ValidationError, ugettext("This value must be a decimal number.")
+ raise validators.ValidationError(
+ _("This value must be a decimal number."))
def _format(self, value):
if isinstance(value, basestring):
@@ -3,10 +3,6 @@
from django.db.models import signals
from django.db.models.fields import FieldDoesNotExist
-# Size of each "chunk" for get_iterator calls.
-# Larger values are slightly faster at the expense of more storage space.
-GET_ITERATOR_CHUNK_SIZE = 100
-
def ensure_default_manager(sender):
cls = sender
if not hasattr(cls, '_default_manager'):
View
@@ -579,28 +579,36 @@ def iterator(self):
except EmptyResultSet:
raise StopIteration
- # self._fields is a list of field names to fetch.
+ # self._select is a dictionary, and dictionaries' key order is
+ # undefined, so we convert it to a list of tuples.
+ extra_select = self._select.items()
+
+ # Construct two objects -- fields and field_names.
+ # fields is a list of Field objects to fetch.
+ # field_names is a list of field names, which will be the keys in the
+ # resulting dictionaries.
if self._fields:
- if not self._select:
+ if not extra_select:
fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields]
+ field_names = self._fields
else:
fields = []
+ field_names = []
for f in self._fields:
if f in [field.name for field in self.model._meta.fields]:
fields.append(self.model._meta.get_field(f, many_to_many=False))
- elif not self._select.has_key( f ):
- raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f )
-
- field_names = self._fields
+ field_names.append(f)
+ elif not self._select.has_key(f):
+ raise FieldDoesNotExist('%s has no field named %r' % (self.model._meta.object_name, f))
else: # Default to all fields.
fields = self.model._meta.fields
field_names = [f.attname for f in fields]
columns = [f.column for f in fields]
select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
- # Add any additional SELECTs.
- if self._select:
- select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
+ if extra_select:
+ select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in extra_select])
+ field_names.extend([f[0] for f in extra_select])
cursor = connection.cursor()
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
View
@@ -232,16 +232,8 @@ def __init__(self, form, field, name):
self.help_text = field.help_text or ''
def __unicode__(self):
- "Renders this field as an HTML widget."
- # Use the 'widget' attribute on the field to determine which type
- # of HTML widget to use.
- value = self.as_widget(self.field.widget)
- if not isinstance(value, basestring):
- # Some Widget render() methods -- notably RadioSelect -- return a
- # "special" object rather than a string. Call __unicode__() on that
- # object to get its rendered value.
- value = unicode(value)
- return value
+ """Renders this field as an HTML widget."""
+ return self.as_widget()
def _errors(self):
"""
@@ -251,7 +243,14 @@ def _errors(self):
return self.form.errors.get(self.name, ErrorList())
errors = property(_errors)
- def as_widget(self, widget, attrs=None):
+ def as_widget(self, widget=None, attrs=None):
+ """
+ Renders the field by rendering the passed widget, adding any HTML
+ attributes passed as attrs. If no widget is specified, then the
+ field's default widget will be used.
+ """
+ if not widget:
+ widget = self.field.widget
attrs = attrs or {}
auto_id = self.auto_id
if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
Oops, something went wrong.

0 comments on commit 0f5a5a0

Please sign in to comment.