Skip to content
Browse files

boulder-oracle-sprint: Merged to [5078]

  • Loading branch information...
1 parent 62ba18d commit 61bef9bbfd20c252851df4f813db39a825c64b52 Boulder Sprinters committed
Showing with 2,790 additions and 2,276 deletions.
  1. +3 −0 AUTHORS
  2. +6 −0 django/conf/global_settings.py
  3. BIN django/conf/locale/fr/LC_MESSAGES/django.mo
  4. +780 −455 django/conf/locale/fr/LC_MESSAGES/django.po
  5. BIN django/conf/locale/ko/LC_MESSAGES/django.mo
  6. +1,793 −1,731 django/conf/locale/ko/LC_MESSAGES/django.po
  7. +0 −2 django/contrib/admin/views/decorators.py
  8. +3 −1 django/contrib/auth/__init__.py
  9. +6 −3 django/contrib/auth/decorators.py
  10. +6 −0 django/contrib/auth/models.py
  11. +11 −4 django/contrib/auth/views.py
  12. +1 −1 django/contrib/comments/templates/comments/form.html
  13. +2 −0 django/contrib/comments/templatetags/comments.py
  14. +4 −2 django/core/serializers/base.py
  15. +7 −6 django/core/serializers/json.py
  16. +2 −1 django/db/__init__.py
  17. +1 −0 django/db/backends/ado_mssql/base.py
  18. +3 −0 django/db/backends/dummy/base.py
  19. +1 −0 django/db/backends/mysql/base.py
  20. +1 −0 django/db/backends/mysql_old/base.py
  21. +1 −0 django/db/backends/oracle/base.py
  22. +1 −0 django/db/backends/postgresql/base.py
  23. +1 −0 django/db/backends/postgresql_psycopg2/base.py
  24. +1 −0 django/db/backends/sqlite3/base.py
  25. +15 −4 django/newforms/widgets.py
  26. +3 −3 django/template/__init__.py
  27. +1 −0 django/template/defaulttags.py
  28. +1 −1 django/utils/cache.py
  29. +13 −6 django/utils/datastructures.py
  30. +7 −8 django/utils/synch.py
  31. +4 −4 django/utils/timesince.py
  32. +2 −2 docs/api_stability.txt
  33. +19 −16 docs/authentication.txt
  34. +3 −3 docs/db-api.txt
  35. +1 −1 docs/faq.txt
  36. +2 −2 docs/flatpages.txt
  37. +1 −1 docs/forms.txt
  38. +1 −1 docs/generic_views.txt
  39. +1 −1 docs/i18n.txt
  40. +16 −7 docs/model-api.txt
  41. +2 −2 docs/redirects.txt
  42. +1 −0 docs/request_response.txt
  43. +1 −1 docs/serialization.txt
  44. +28 −1 docs/settings.txt
  45. +2 −2 docs/sites.txt
  46. +1 −1 docs/syndication_feeds.txt
  47. +1 −1 docs/tutorial01.txt
  48. +1 −1 docs/tutorial04.txt
  49. +2 −0 tests/regressiontests/datastructures/tests.py
  50. +26 −0 tests/regressiontests/forms/tests.py
  51. +1 −1 tests/regressiontests/templates/tests.py
View
3 AUTHORS
@@ -49,6 +49,7 @@ answer newbie questions, and generally made Django that much better:
ant9000@netwise.it
David Ascher <http://ascher.ca/>
Arthur <avandorp@gmail.com>
+ axiak@mit.edu
Jiri Barton
Ned Batchelder <http://www.nedbatchelder.com/>
Shannon -jj Behrens <http://jjinux.blogspot.com/>
@@ -84,6 +85,7 @@ answer newbie questions, and generally made Django that much better:
Jeremy Dunck <http://dunck.us/>
Andy Dustman <farcepest@gmail.com>
Clint Ecker
+ enlight
Enrico <rico.bl@gmail.com>
Ludvig Ericson <ludvig.ericson@gmail.com>
Dirk Eschler <dirk.eschler@gmx.net>
@@ -108,6 +110,7 @@ answer newbie questions, and generally made Django that much better:
hipertracker@gmail.com
Ian Holsman <http://feh.holsman.net/>
Kieran Holland <http://www.kieranholland.com>
+ Sung-Jin Hong <serialx.net@gmail.com>
Robert Rock Howard <http://djangomojo.com/>
Jason Huggins <http://www.jrandolph.com/blog/>
Hyun Mi Ae
View
6 django/conf/global_settings.py
@@ -312,6 +312,12 @@
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
+LOGIN_URL = '/accounts/login/'
+
+LOGOUT_URL = '/accounts/logout/'
+
+LOGIN_REDIRECT_URL = '/accounts/profile/'
+
###########
# TESTING #
###########
View
BIN django/conf/locale/fr/LC_MESSAGES/django.mo
Binary file not shown.
View
1,235 django/conf/locale/fr/LC_MESSAGES/django.po
780 additions, 455 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
BIN django/conf/locale/ko/LC_MESSAGES/django.mo
Binary file not shown.
View
3,524 django/conf/locale/ko/LC_MESSAGES/django.po
1,793 additions, 1,731 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
2 django/contrib/admin/views/decorators.py
@@ -90,8 +90,6 @@ def _checklogin(request, *args, **kwargs):
if user.is_active and user.is_staff:
login(request, user)
# TODO: set last_login with an event.
- user.last_login = datetime.datetime.now()
- user.save()
if request.POST.has_key('post_data'):
post_data = _decode_post_data(request.POST['post_data'])
if post_data and not post_data.has_key(LOGIN_FORM_KEY):
View
4 django/contrib/auth/__init__.py
@@ -1,8 +1,8 @@
+import datetime
from django.core.exceptions import ImproperlyConfigured
SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
-LOGIN_URL = '/accounts/login/'
REDIRECT_FIELD_NAME = 'next'
def load_backend(path):
@@ -49,6 +49,8 @@ def login(request, user):
if user is None:
user = request.user
# TODO: It would be nice to support different login methods, like signed cookies.
+ user.last_login = datetime.datetime.now()
+ user.save()
request.session[SESSION_KEY] = user.id
request.session[BACKEND_SESSION_KEY] = user.backend
View
9 django/contrib/auth/decorators.py
@@ -1,13 +1,16 @@
-from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
+from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect
from urllib import quote
-def user_passes_test(test_func, login_url=LOGIN_URL):
+def user_passes_test(test_func, login_url=None):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
+ if not login_url:
+ from django.conf import settings
+ login_url = settings.LOGIN_URL
def _dec(view_func):
def _checklogin(request, *args, **kwargs):
if test_func(request.user):
@@ -27,7 +30,7 @@ def _checklogin(request, *args, **kwargs):
"""
)
-def permission_required(perm, login_url=LOGIN_URL):
+def permission_required(perm, login_url=None):
"""
Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary.
View
6 django/contrib/auth/models.py
@@ -17,6 +17,12 @@ def check_password(raw_password, enc_password):
elif algo == 'sha1':
import sha
return hsh == sha.new(salt+raw_password).hexdigest()
+ elif algo == 'crypt':
+ try:
+ import crypt
+ except ImportError:
+ raise ValueError, "Crypt password algorithm not supported in this environment."
+ return hsh == crypt.crypt(raw_password, salt)
raise ValueError, "Got unknown password algorithm type in password."
class SiteProfileNotAvailable(Exception):
View
15 django/contrib/auth/views.py
@@ -6,7 +6,7 @@
from django.contrib.sites.models import Site
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
-from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
+from django.contrib.auth import REDIRECT_FIELD_NAME
def login(request, template_name='registration/login.html'):
"Displays the login form and handles the login action."
@@ -17,7 +17,8 @@ def login(request, template_name='registration/login.html'):
if not errors:
# Light security check -- make sure redirect_to isn't garbage.
if not redirect_to or '://' in redirect_to or ' ' in redirect_to:
- redirect_to = '/accounts/profile/'
+ from django.conf import settings
+ redirect_to = settings.LOGIN_REDIRECT_URL
from django.contrib.auth import login
login(request, manipulator.get_user())
request.session.delete_test_cookie()
@@ -41,12 +42,18 @@ def logout(request, next_page=None, template_name='registration/logged_out.html'
# Redirect to this page until the session has been cleared.
return HttpResponseRedirect(next_page or request.path)
-def logout_then_login(request, login_url=LOGIN_URL):
+def logout_then_login(request, login_url=None):
"Logs out the user if he is logged in. Then redirects to the log-in page."
+ if not login_url:
+ from django.conf import settings
+ login_url = settings.LOGIN_URL
return logout(request, login_url)
-def redirect_to_login(next, login_url=LOGIN_URL):
+def redirect_to_login(next, login_url=None):
"Redirects the user to the login page, passing the given 'next' page"
+ if not login_url:
+ from django.conf import settings
+ login_url = settings.LOGIN_URL
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
View
2 django/contrib/comments/templates/comments/form.html
@@ -3,7 +3,7 @@
<form {% if photos_optional or photos_required %}enctype="multipart/form-data" {% endif %}action="/comments/post/" method="post">
{% if user.is_authenticated %}
-<p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="/accounts/logout/">{% trans "Log out" %}</a>)</p>
+<p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="{{ logout_url }}">{% trans "Log out" %}</a>)</p>
{% else %}
<p><label for="id_username">{% trans "Username:" %}</label> <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p>
{% endif %}
View
2 django/contrib/comments/templatetags/comments.py
@@ -25,6 +25,7 @@ def __init__(self, content_type, obj_id_lookup_var, obj_id, free,
self.is_public = is_public
def render(self, context):
+ from django.conf import settings
from django.utils.text import normalize_newlines
import base64
context.push()
@@ -64,6 +65,7 @@ def render(self, context):
if self.rating_options:
context['rating_range'], context['rating_choices'] = Comment.objects.get_rating_options(self.rating_options)
context['hash'] = Comment.objects.get_security_hash(context['options'], context['photo_options'], context['rating_options'], context['target'])
+ context['logout_url'] = settings.LOGOUT_URL
default_form = loader.get_template(COMMENT_FORM)
output = default_form.render(context)
context.pop()
View
6 django/core/serializers/base.py
@@ -105,9 +105,11 @@ def handle_m2m_field(self, obj, field):
def getvalue(self):
"""
- Return the fully serialized queryset.
+ Return the fully serialized queryset (or None if the output stream is
+ not seekable).
"""
- return self.stream.getvalue()
+ if callable(getattr(self.stream, 'getvalue', None)):
+ return self.stream.getvalue()
class Deserializer(object):
"""
View
13 django/core/serializers/json.py
@@ -17,9 +17,10 @@ class Serializer(PythonSerializer):
"""
def end_serialization(self):
simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder, **self.options)
-
+
def getvalue(self):
- return self.stream.getvalue()
+ if callable(getattr(self.stream, 'getvalue', None)):
+ return self.stream.getvalue()
def Deserializer(stream_or_string, **options):
"""
@@ -31,15 +32,15 @@ def Deserializer(stream_or_string, **options):
stream = stream_or_string
for obj in PythonDeserializer(simplejson.load(stream)):
yield obj
-
+
class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
"""
JSONEncoder subclass that knows how to encode date/time types
"""
-
- DATE_FORMAT = "%Y-%m-%d"
+
+ DATE_FORMAT = "%Y-%m-%d"
TIME_FORMAT = "%H:%M:%S"
-
+
def default(self, o):
if isinstance(o, datetime.datetime):
return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
View
3 django/db/__init__.py
@@ -2,7 +2,7 @@
from django.core import signals
from django.dispatch import dispatcher
-__all__ = ('backend', 'connection', 'DatabaseError')
+__all__ = ('backend', 'connection', 'DatabaseError', 'IntegrityError')
if not settings.DATABASE_ENGINE:
settings.DATABASE_ENGINE = 'dummy'
@@ -29,6 +29,7 @@
connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)
DatabaseError = backend.DatabaseError
+IntegrityError = backend.IntegrityError
# Register an event that closes the database connection
# when a Django request is finished.
View
1 django/db/backends/ado_mssql/base.py
@@ -17,6 +17,7 @@
mx = None
DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
# We need to use a special Cursor class because adodbapi expects question-mark
# param style, but Django expects "%s". This cursor converts question marks to
View
3 django/db/backends/dummy/base.py
@@ -15,6 +15,9 @@ def complain(*args, **kwargs):
class DatabaseError(Exception):
pass
+class IntegrityError(DatabaseError):
+ pass
+
class DatabaseWrapper:
cursor = complain
_commit = complain
View
1 django/db/backends/mysql/base.py
@@ -25,6 +25,7 @@
import re
DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
# MySQLdb-1.2.1 supports the Python boolean type, and only uses datetime
# module for time-related columns; older versions could have used mx.DateTime
View
1 django/db/backends/mysql_old/base.py
@@ -16,6 +16,7 @@
import re
DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
django_conversions = conversions.copy()
django_conversions.update({
View
1 django/db/backends/oracle/base.py
@@ -16,6 +16,7 @@
DatabaseError = Database.Error
+IntegrityError = Database.IntegrityError
try:
# Only exists in Python 2.4+
View
1 django/db/backends/postgresql/base.py
@@ -12,6 +12,7 @@
raise ImproperlyConfigured, "Error loading psycopg module: %s" % e
DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
try:
# Only exists in Python 2.4+
View
1 django/db/backends/postgresql_psycopg2/base.py
@@ -12,6 +12,7 @@
raise ImproperlyConfigured, "Error loading psycopg2 module: %s" % e
DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
try:
# Only exists in Python 2.4+
View
1 django/db/backends/sqlite3/base.py
@@ -18,6 +18,7 @@
raise ImproperlyConfigured, "Error loading %s module: %s" % (module, e)
DatabaseError = Database.DatabaseError
+IntegrityError = Database.IntegrityError
Database.register_converter("bool", lambda s: str(s) == '1')
Database.register_converter("time", util.typecast_time)
View
19 django/newforms/widgets.py
@@ -260,8 +260,8 @@ def render(self, name, value, attrs=None, choices=()):
"Returns a RadioFieldRenderer instance rather than a Unicode string."
if value is None: value = ''
str_value = smart_unicode(value) # Normalize to string.
- attrs = attrs or {}
- return RadioFieldRenderer(name, str_value, attrs, list(chain(self.choices, choices)))
+ final_attrs = self.build_attrs(attrs)
+ return RadioFieldRenderer(name, str_value, final_attrs, list(chain(self.choices, choices)))
def id_for_label(self, id_):
# RadioSelect is represented by multiple <input type="radio"> fields,
@@ -327,14 +327,25 @@ def render(self, name, value, attrs=None):
if not isinstance(value, list):
value = self.decompress(value)
output = []
+ final_attrs = self.build_attrs(attrs)
+ id_ = final_attrs.get('id', None)
for i, widget in enumerate(self.widgets):
try:
widget_value = value[i]
- except KeyError:
+ except IndexError:
widget_value = None
- output.append(widget.render(name + '_%s' % i, widget_value, attrs))
+ if id_:
+ final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
+ output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
return self.format_output(output)
+ def id_for_label(self, id_):
+ # See the comment for RadioSelect.id_for_label()
+ if id_:
+ id_ += '_0'
+ return id_
+ id_for_label = classmethod(id_for_label)
+
def value_from_datadict(self, data, name):
return [data.get(name + '_%s' % i) for i in range(len(self.widgets))]
View
6 django/template/__init__.py
@@ -123,10 +123,10 @@ class VariableDoesNotExist(Exception):
def __init__(self, msg, params=()):
self.msg = msg
self.params = params
-
+
def __str__(self):
return self.msg % self.params
-
+
class InvalidTemplateLibrary(Exception):
pass
@@ -555,7 +555,7 @@ def __init__(self, token, parser):
filters.append( (filter_func,args))
upto = match.end()
if upto != len(token):
- raise TemplateSyntaxError, "Could not parse the remainder: %s" % token[upto:]
+ raise TemplateSyntaxError, "Could not parse the remainder: '%s' from '%s'" % (token[upto:], token)
self.var, self.filters = var, filters
def resolve(self, context, ignore_failures=False):
View
1 django/template/defaulttags.py
@@ -956,6 +956,7 @@ def url(parser, token):
for arg in bits[2].split(','):
if '=' in arg:
k, v = arg.split('=', 1)
+ k = k.strip()
kwargs[k] = parser.compile_filter(v)
else:
args.append(parser.compile_filter(arg))
View
2 django/utils/cache.py
@@ -86,7 +86,7 @@ def patch_response_headers(response, cache_timeout=None):
def add_never_cache_headers(response):
"""
- Add headers to a response to indicate that
+ Add headers to a response to indicate that
a page should never be cached.
"""
patch_response_headers(response, cache_timeout=-1)
View
19 django/utils/datastructures.py
@@ -16,9 +16,9 @@ def __getitem__(self, key):
def __contains__(self, key):
return self.has_key(key)
-
- def __copy__(self):
- return self.__class__(*self.dicts)
+
+ def __copy__(self):
+ return self.__class__(*self.dicts)
def get(self, key, default=None):
try:
@@ -45,9 +45,9 @@ def has_key(self, key):
if dict.has_key(key):
return True
return False
-
- def copy(self):
- """ returns a copy of this object"""
+
+ def copy(self):
+ """ returns a copy of this object"""
return self.__copy__()
class SortedDict(dict):
@@ -99,6 +99,13 @@ def copy(self):
obj.keyOrder = self.keyOrder
return obj
+ def __repr__(self):
+ """
+ Replaces the normal dict.__repr__ with a version that returns the keys
+ in their sorted order.
+ """
+ return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()])
+
class MultiValueDictKeyError(KeyError):
pass
View
15 django/utils/synch.py
@@ -1,6 +1,6 @@
"""
Synchronization primitives:
-
+
- reader-writer lock (preference to writers)
(Contributed to Django by eugene@lazutkin.com)
@@ -14,17 +14,16 @@
class RWLock:
"""
Classic implementation of reader-writer lock with preference to writers.
-
+
Readers can access a resource simultaneously.
Writers get an exclusive access.
-
+
API is self-descriptive:
reader_enters()
reader_leaves()
writer_enters()
writer_leaves()
"""
-
def __init__(self):
self.mutex = threading.RLock()
self.can_read = threading.Semaphore(0)
@@ -33,7 +32,7 @@ def __init__(self):
self.active_writers = 0
self.waiting_readers = 0
self.waiting_writers = 0
-
+
def reader_enters(self):
self.mutex.acquire()
try:
@@ -45,7 +44,7 @@ def reader_enters(self):
finally:
self.mutex.release()
self.can_read.acquire()
-
+
def reader_leaves(self):
self.mutex.acquire()
try:
@@ -56,7 +55,7 @@ def reader_leaves(self):
self.can_write.release()
finally:
self.mutex.release()
-
+
def writer_enters(self):
self.mutex.acquire()
try:
@@ -68,7 +67,7 @@ def writer_enters(self):
finally:
self.mutex.release()
self.can_write.acquire()
-
+
def writer_leaves(self):
self.mutex.acquire()
try:
View
8 django/utils/timesince.py
@@ -1,6 +1,6 @@
import datetime, math, time
from django.utils.tzinfo import LocalTimezone
-from django.utils.translation import ngettext
+from django.utils.translation import ngettext, gettext
def timesince(d, now=None):
"""
@@ -37,14 +37,14 @@ def timesince(d, now=None):
if count != 0:
break
if count < 0:
- return '%d milliseconds' % math.floor((now - d).microseconds / 1000)
- s = '%d %s' % (count, name(count))
+ return gettext('%d milliseconds') % math.floor((now - d).microseconds / 1000)
+ s = gettext('%(number)d %(type)s') % {'number': count, 'type': name(count)}
if i + 1 < len(chunks):
# Now get the second item
seconds2, name2 = chunks[i + 1]
count2 = (since - (seconds * count)) / seconds2
if count2 != 0:
- s += ', %d %s' % (count2, name2(count2))
+ s += gettext(', %(number)d %(type)s') % {'number': count2, 'type': name2(count2)}
return s
def timeuntil(d, now=None):
View
4 docs/api_stability.txt
@@ -100,14 +100,14 @@ change:
.. _caching: ../cache/
.. _custom template tags and libraries: ../templates_python/
-.. _database lookup: ../db_api/
+.. _database lookup: ../db-api/
.. _django-admin utility: ../django-admin/
.. _fastcgi integration: ../fastcgi/
.. _flatpages: ../flatpages/
.. _generic views: ../generic_views/
.. _internationalization: ../i18n/
.. _legacy database integration: ../legacy_databases/
-.. _model definition: ../model_api/
+.. _model definition: ../model-api/
.. _mod_python integration: ../modpython/
.. _redirects: ../redirects/
.. _request/response objects: ../request_response/
View
35 docs/authentication.txt
@@ -144,7 +144,7 @@ custom methods:
Raises ``django.contrib.auth.models.SiteProfileNotAvailable`` if the current site
doesn't allow profiles.
-.. _Django model: ../model_api/
+.. _Django model: ../model-api/
.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email
Manager functions
@@ -204,9 +204,11 @@ The ``password`` attribute of a ``User`` object is a string in this format::
That's hashtype, salt and hash, separated by the dollar-sign character.
-Hashtype is either ``sha1`` (default) or ``md5`` -- the algorithm used to
-perform a one-way hash of the password. Salt is a random string used to salt
-the raw password to create the hash.
+Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm
+used to perform a one-way hash of the password. Salt is a random string used
+to salt the raw password to create the hash. Note that the ``crypt`` method is
+only supported on platforms that have the standard Python ``crypt`` module
+available.
For example::
@@ -387,14 +389,15 @@ introduced in Python 2.4::
``login_required`` does the following:
- * If the user isn't logged in, redirect to ``/accounts/login/``, passing
- the current absolute URL in the query string as ``next``. For example:
+ * If the user isn't logged in, redirect to ``settings.LOGIN_URL``
+ (``/accounts/login/`` by default), passing the current absolute URL
+ in the query string as ``next``. For example:
``/accounts/login/?next=/polls/3/``.
* If the user is logged in, execute the view normally. The view code is
free to assume the user is logged in.
-Note that you'll need to map the appropriate Django view to ``/accounts/login/``.
-To do this, add the following line to your URLconf::
+Note that you'll need to map the appropriate Django view to ``settings.LOGIN_URL``.
+For example, using the defaults, add the following line to your URLconf::
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
@@ -405,9 +408,9 @@ Here's what ``django.contrib.auth.views.login`` does:
* If called via ``POST``, it tries to log the user in. If login is
successful, the view redirects to the URL specified in ``next``. If
- ``next`` isn't provided, it redirects to ``/accounts/profile/`` (which is
- currently hard-coded). If login isn't successful, it redisplays the login
- form.
+ ``next`` isn't provided, it redirects to ``settings.LOGIN_REDIRECT_URL``
+ (which defaults to ``/accounts/profile/``). If login isn't successful,
+ it redisplays the login form.
It's your responsibility to provide the login form in a template called
``registration/login.html`` by default. This template gets passed three
@@ -487,7 +490,7 @@ Logs a user out, then redirects to the login page.
**Optional arguments:**
* ``login_url``: The URL of the login page to redirect to. This
- will default to ``/accounts/login/`` if not supplied.
+ will default to ``settings.LOGIN_URL`` if not supplied.
``django.contrib.auth.views.password_change``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -569,7 +572,7 @@ successful login.
**Optional arguments:**
* ``login_url``: The URL of the login page to redirect to. This
- will default to ``/accounts/login/`` if not supplied.
+ will default to ``settings.LOGIN_URL`` if not supplied.
Built-in manipulators
---------------------
@@ -636,7 +639,7 @@ Note that ``user_passes_test`` does not automatically check that the ``User``
is not anonymous.
``user_passes_test()`` takes an optional ``login_url`` argument, which lets you
-specify the URL for your login page (``/accounts/login/`` by default).
+specify the URL for your login page (``settings.LOGIN_URL`` by default).
Example in Python 2.3 syntax::
@@ -680,7 +683,7 @@ parameter. Example::
my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view)
As in the ``login_required`` decorator, ``login_url`` defaults to
-``'/accounts/login/'``.
+``settings.LOGIN_URL``.
Limiting access to generic views
--------------------------------
@@ -757,7 +760,7 @@ This example model creates three custom permissions::
The only thing this does is create those extra permissions when you run
``syncdb``.
-.. _model Meta attribute: ../model_api/#meta-options
+.. _model Meta attribute: ../model-api/#meta-options
API reference
-------------
View
6 docs/db-api.txt
@@ -6,7 +6,7 @@ Once you've created your `data models`_, Django automatically gives you a
database-abstraction API that lets you create, retrieve, update and delete
objects. This document explains that API.
-.. _`data models`: ../model_api/
+.. _`data models`: ../model-api/
Throughout this reference, we'll refer to the following models, which comprise
a weblog application::
@@ -85,7 +85,7 @@ There's no way to tell what the value of an ID will be before you call
unless you explicitly specify ``primary_key=True`` on a field. See the
`AutoField documentation`_.)
-.. _AutoField documentation: ../model_api/#autofield
+.. _AutoField documentation: ../model-api/#autofield
Explicitly specifying auto-primary-key values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1801,4 +1801,4 @@ interface to your database. You can access your database via other tools,
programming languages or database frameworks; there's nothing Django-specific
about your database.
-.. _Executing custom SQL: ../model_api/#executing-custom-sql
+.. _Executing custom SQL: ../model-api/#executing-custom-sql
View
2 docs/faq.txt
@@ -513,7 +513,7 @@ type, create an initial data file and put something like this in it::
As explained in the `SQL initial data file`_ documentation, this SQL file can
contain arbitrary SQL, so you can make any sorts of changes you need to make.
-.. _SQL initial data file: ../model_api/#providing-initial-sql-data
+.. _SQL initial data file: ../model-api/#providing-initial-sql-data
Why is Django leaking memory?
-----------------------------
View
4 docs/flatpages.txt
@@ -84,9 +84,9 @@ Flatpages are represented by a standard `Django model`_, which lives in
`django/contrib/flatpages/models.py`_. You can access flatpage objects via the
`Django database API`_.
-.. _Django model: ../model_api/
+.. _Django model: ../model-api/
.. _django/contrib/flatpages/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/flatpages/models.py
-.. _Django database API: ../db_api/
+.. _Django database API: ../db-api/
Flatpage templates
==================
View
2 docs/forms.txt
@@ -691,5 +691,5 @@ fails. If no message is passed in, a default message is used.
document for more details).
.. _`generic views`: ../generic_views/
-.. _`models API`: ../model_api/
+.. _`models API`: ../model-api/
.. _settings: ../settings/
View
2 docs/generic_views.txt
@@ -71,7 +71,7 @@ are first evaluated, so if you want to pass in a QuerySet via
``extra_context`` that is always fresh you need to wrap it in a function or
lambda that returns the QuerySet.
-.. _database API docs: ../db_api/
+.. _database API docs: ../db-api/
"Simple" generic views
======================
View
2 docs/i18n.txt
@@ -175,7 +175,7 @@ class, though::
verbose_name = _('my thing')
verbose_name_plural = _('mythings')
-.. _Django models: ../model_api/
+.. _Django models: ../model-api/
Pluralization
~~~~~~~~~~~~~
View
23 docs/model-api.txt
@@ -194,14 +194,23 @@ This doesn't accept ``maxlength``; its ``maxlength`` is automatically set to
``FileField``
~~~~~~~~~~~~~
-A file-upload field.
+A file-upload field. Has one **required** argument:
-Has an extra required argument, ``upload_to``, a local filesystem path to
-which files should be upload. This path may contain `strftime formatting`_,
-which will be replaced by the date/time of the file upload (so that
-uploaded files don't fill up the given directory).
+ ====================== ===================================================
+ Argument Description
+ ====================== ===================================================
+ ``upload_to`` A local filesystem path that will be appended to
+ your ``MEDIA_ROOT`` setting to determine the
+ output of the ``get_<fieldname>_url()`` helper
+ function.
+ ====================== ===================================================
+
+This path may contain `strftime formatting`_, which will be replaced by the
+date/time of the file upload (so that uploaded files don't fill up the given
+directory).
-The admin represents this as an ``<input type="file">`` (a file-upload widget).
+The admin represents this field as an ``<input type="file">`` (a file-upload
+widget).
Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few
steps:
@@ -246,7 +255,7 @@ visiting its URL on your site. Don't allow that.
A field whose choices are limited to the filenames in a certain directory
on the filesystem. Has three special arguments, of which the first is
-required:
+**required**:
====================== ===================================================
Argument Description
View
4 docs/redirects.txt
@@ -66,6 +66,6 @@ Redirects are represented by a standard `Django model`_, which lives in
`django/contrib/redirects/models.py`_. You can access redirect
objects via the `Django database API`_.
-.. _Django model: ../model_api/
+.. _Django model: ../model-api/
.. _django/contrib/redirects/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/redirects/models.py
-.. _Django database API: ../db_api/
+.. _Django database API: ../db-api/
View
1 docs/request_response.txt
@@ -93,6 +93,7 @@ All attributes except ``session`` should be considered read-only.
* ``CONTENT_TYPE``
* ``HTTP_ACCEPT_ENCODING``
* ``HTTP_ACCEPT_LANGUAGE``
+ * ``HTTP_HOST`` -- The HTTP Host header sent by the client.
* ``HTTP_REFERER`` -- The referring page, if any.
* ``HTTP_USER_AGENT`` -- The client's user-agent string.
* ``QUERY_STRING`` -- The query string, as a single (unparsed) string.
View
2 docs/serialization.txt
@@ -27,7 +27,7 @@ data to (see `Serialization formats`_) and a QuerySet_ to serialize.
(Actually, the second argument can be any iterator that yields Django objects,
but it'll almost always be a QuerySet).
-.. _QuerySet: ../db_api/#retrieving-objects
+.. _QuerySet: ../db-api/#retrieving-objects
You can also use a serializer object directly::
View
29 docs/settings.txt
@@ -562,6 +562,21 @@ strings for translation, but the translation won't happen at runtime -- so
you'll have to remember to wrap the languages in the *real* ``gettext()`` in
any code that uses ``LANGUAGES`` at runtime.
+LOGIN_URL
+---------
+
+Default: ``'/accounts/login/'``
+
+The URL where requests are redirected for login, specially when using the
+`@login_required`_ decorator.
+
+LOGOUT_URL
+----------
+
+Default: ``'/accounts/logout/'``
+
+LOGIN_URL counterpart.
+
MANAGERS
--------
@@ -620,6 +635,16 @@ locales have different formats. For example, U.S. English would say
See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
TIME_FORMAT and YEAR_MONTH_FORMAT.
+LOGIN_REDIRECT_URL
+------------------
+
+Default: ``'/accounts/profile/'``
+
+The URL where requests are redirected after login when the
+``contrib.auth.login`` view gets no ``next`` parameter.
+
+This is used by the `@login_required`_ decorator, for example.
+
PREPEND_WWW
-----------
@@ -874,7 +899,7 @@ Default: ``Django/<version> (http://www.djangoproject.com/)``
The string to use as the ``User-Agent`` header when checking to see if URLs
exist (see the ``verify_exists`` option on URLField_).
-.. _URLField: ../model_api/#urlfield
+.. _URLField: ../model-api/#urlfield
USE_ETAGS
---------
@@ -1012,6 +1037,8 @@ Also, it's an error to call ``configure()`` more than once, or to call
It boils down to this: Use exactly one of either ``configure()`` or
``DJANGO_SETTINGS_MODULE``. Not both, and not neither.
+.. _@login_required: ../authentication/#the-login-required-decorator
+
Error reporting via e-mail
==========================
View
4 docs/sites.txt
@@ -276,8 +276,8 @@ you want your admin site to have access to all objects (not just site-specific
ones), put ``objects = models.Manager()`` in your model, before you define
``CurrentSiteManager``.
-.. _manager: ../model_api/#managers
-.. _manager documentation: ../model_api/#managers
+.. _manager: ../model-api/#managers
+.. _manager documentation: ../model-api/#managers
How Django uses the sites framework
===================================
View
2 docs/syndication_feeds.txt
@@ -159,7 +159,7 @@ put into those elements.
{{ obj.description }}
.. _chicagocrime.org: http://www.chicagocrime.org/
-.. _object-relational mapper: ../db_api/
+.. _object-relational mapper: ../db-api/
.. _Django templates: ../templates/
A complex example
View
2 docs/tutorial01.txt
@@ -577,5 +577,5 @@ For full details on the database API, see our `Database API reference`_.
When you're comfortable with the API, read `part 2 of this tutorial`_ to get
Django's automatic admin working.
-.. _Database API reference: ../db_api/
+.. _Database API reference: ../db-api/
.. _part 2 of this tutorial: ../tutorial02/
View
2 docs/tutorial04.txt
@@ -219,7 +219,7 @@ template. Note that we use ``dict()`` to return an altered dictionary in place.
If you'd like to know more about how that works, The Django database API
documentation `explains the lazy nature of QuerySet objects`_.
-.. _explains the lazy nature of QuerySet objects: ../db_api/#querysets-are-lazy
+.. _explains the lazy nature of QuerySet objects: ../db-api/#querysets-are-lazy
In previous parts of the tutorial, the templates have been provided with a context
that contains the ``poll`` and ``latest_poll_list`` context variables. However,
View
2 tests/regressiontests/datastructures/tests.py
@@ -52,6 +52,8 @@
'not one'
>>> d.keys() == d.copy().keys()
True
+>>> print repr(d)
+{'one': 'not one', 'two': 'two', 'three': 'three'}
### DotExpandedDict ############################################################
View
26 tests/regressiontests/forms/tests.py
@@ -658,10 +658,31 @@
...
IndexError: list index out of range
+# Unicode choices are correctly rendered as HTML
>>> w = RadioSelect()
>>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]))
u'<ul>\n<li><label><input checked="checked" type="radio" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="radio" name="email" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>'
+# Attributes provided at instantiation are passed to the constituent inputs
+>>> w = RadioSelect(attrs={'id':'foo'})
+>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
+<ul>
+<li><label><input checked="checked" type="radio" id="foo_0" value="J" name="beatle" /> John</label></li>
+<li><label><input type="radio" id="foo_1" value="P" name="beatle" /> Paul</label></li>
+<li><label><input type="radio" id="foo_2" value="G" name="beatle" /> George</label></li>
+<li><label><input type="radio" id="foo_3" value="R" name="beatle" /> Ringo</label></li>
+</ul>
+
+# Attributes provided at render-time are passed to the constituent inputs
+>>> w = RadioSelect()
+>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')), attrs={'id':'bar'})
+<ul>
+<li><label><input checked="checked" type="radio" id="bar_0" value="J" name="beatle" /> John</label></li>
+<li><label><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li>
+<li><label><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li>
+<li><label><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li>
+</ul>
+
# CheckboxSelectMultiple Widget ###############################################
>>> w = CheckboxSelectMultiple()
@@ -783,6 +804,11 @@
u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />'
>>> w.render('name', 'john__lennon')
u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />'
+>>> w.render('name', 'john__lennon', attrs={'id':'foo'})
+u'<input id="foo_0" type="text" class="big" value="john" name="name_0" /><br /><input id="foo_1" type="text" class="small" value="lennon" name="name_1" />'
+>>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'})), attrs={'id': 'bar'})
+>>> w.render('name', ['john', 'lennon'])
+u'<input id="bar_0" type="text" class="big" value="john" name="name_0" /><br /><input id="bar_1" type="text" class="small" value="lennon" name="name_1" />'
# SplitDateTimeWidget #########################################################
View
2 tests/regressiontests/templates/tests.py
@@ -694,7 +694,7 @@ def test_templates(self):
### URL TAG ########################################################
# Successes
'url01' : ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
- 'url02' : ('{% url regressiontests.templates.views.client_action client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
+ 'url02' : ('{% url regressiontests.templates.views.client_action client.id, action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
'url03' : ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
'url04' : ('{% url named-client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),

0 comments on commit 61bef9b

Please sign in to comment.
Something went wrong with that request. Please try again.