summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2007-09-15 21:46:18 +0000
committerAdrian Holovaty <adrian@holovaty.com>2007-09-15 21:46:18 +0000
commit7325fbf4ff20f9b0f21d3a1aba1abaca78a765d7 (patch)
tree8276758a973d926f7fa43377b5ef4d07ed2eb517 /django
parent5ce2e6c2c827cf877f73bf0e42e6afb7e6a71ccf (diff)
queryset-refactor: Merged to [6250]
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6339 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
-rw-r--r--django/contrib/auth/decorators.py4
-rw-r--r--django/contrib/comments/views/comments.py16
-rw-r--r--django/contrib/comments/views/karma.py6
-rw-r--r--django/contrib/comments/views/userflags.py24
-rw-r--r--django/contrib/formtools/preview.py42
-rw-r--r--django/contrib/webdesign/templatetags/webdesign.py2
-rw-r--r--django/contrib/webdesign/tests.py4
-rw-r--r--django/core/handlers/base.py2
-rw-r--r--django/core/handlers/modpython.py4
-rw-r--r--django/core/handlers/wsgi.py2
-rw-r--r--django/core/management/commands/shell.py13
-rw-r--r--django/core/management/validation.py3
-rw-r--r--django/db/backends/mysql/base.py9
-rw-r--r--django/db/backends/oracle/base.py20
-rw-r--r--django/http/__init__.py20
-rw-r--r--django/middleware/gzip.py2
-rw-r--r--django/shortcuts/__init__.py2
-rw-r--r--django/template/defaultfilters.py11
-rw-r--r--django/utils/cache.py4
-rw-r--r--django/utils/feedgenerator.py5
20 files changed, 105 insertions, 90 deletions
diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py
index de0dc21c5d..b6481ea52c 100644
--- a/django/contrib/auth/decorators.py
+++ b/django/contrib/auth/decorators.py
@@ -1,6 +1,6 @@
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect
-from urllib import quote
+from django.utils.http import urlquote
def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
@@ -15,7 +15,7 @@ def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIE
def _checklogin(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
- return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, quote(request.get_full_path())))
+ return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, urlquote(request.get_full_path())))
_checklogin.__doc__ = view_func.__doc__
_checklogin.__dict__ = view_func.__dict__
diff --git a/django/contrib/comments/views/comments.py b/django/contrib/comments/views/comments.py
index fbec04c8eb..67da5759ac 100644
--- a/django/contrib/comments/views/comments.py
+++ b/django/contrib/comments/views/comments.py
@@ -155,7 +155,7 @@ class PublicFreeCommentManipulator(oldforms.Manipulator):
c.save()
return c
-def post_comment(request):
+def post_comment(request, extra_context=None, context_processors=None):
"""
Post a comment
@@ -185,6 +185,7 @@ def post_comment(request):
rating_choices
choice of ratings
"""
+ if extra_context is None: extra_context = {}
if not request.POST:
raise Http404, _("Only POSTs are allowed")
try:
@@ -244,7 +245,7 @@ def post_comment(request):
'ratings_required': RATINGS_REQUIRED in option_list,
'rating_range': rating_range,
'rating_choices': rating_choices,
- }, context_instance=RequestContext(request))
+ }, context_instance=RequestContext(request, extra_context, context_processors))
elif 'post' in request.POST:
# If the IP is banned, mail the admins, do NOT save the comment, and
# serve up the "Thanks for posting" page as if the comment WAS posted.
@@ -257,7 +258,7 @@ def post_comment(request):
else:
raise Http404, _("The comment form didn't provide either 'preview' or 'post'")
-def post_free_comment(request):
+def post_free_comment(request, extra_context=None, context_processors=None):
"""
Post a free comment (not requiring a log in)
@@ -277,6 +278,7 @@ def post_free_comment(request):
security hash (must be included in a posted form to succesfully
post a comment).
"""
+ if extra_context is None: extra_context = {}
if not request.POST:
raise Http404, _("Only POSTs are allowed")
try:
@@ -307,7 +309,7 @@ def post_free_comment(request):
'options': options,
'target': target,
'hash': security_hash,
- }, context_instance=RequestContext(request))
+ }, context_instance=RequestContext(request, extra_context, context_processors))
elif 'post' in request.POST:
# If the IP is banned, mail the admins, do NOT save the comment, and
# serve up the "Thanks for posting" page as if the comment WAS posted.
@@ -321,7 +323,7 @@ def post_free_comment(request):
else:
raise Http404, _("The comment form didn't provide either 'preview' or 'post'")
-def comment_was_posted(request):
+def comment_was_posted(request, extra_context=None, context_processors=None):
"""
Display "comment was posted" success page
@@ -330,6 +332,7 @@ def comment_was_posted(request):
object
The object the comment was posted on
"""
+ if extra_context is None: extra_context = {}
obj = None
if 'c' in request.GET:
content_type_id, object_id = request.GET['c'].split(':')
@@ -338,4 +341,5 @@ def comment_was_posted(request):
obj = content_type.get_object_for_this_type(pk=object_id)
except ObjectDoesNotExist:
pass
- return render_to_response('comments/posted.html', {'object': obj}, context_instance=RequestContext(request))
+ return render_to_response('comments/posted.html', {'object': obj},
+ context_instance=RequestContext(request, extra_context, context_processors))
diff --git a/django/contrib/comments/views/karma.py b/django/contrib/comments/views/karma.py
index c6ad301dee..7c0e284ae9 100644
--- a/django/contrib/comments/views/karma.py
+++ b/django/contrib/comments/views/karma.py
@@ -4,7 +4,7 @@ from django.template import RequestContext
from django.contrib.comments.models import Comment, KarmaScore
from django.utils.translation import ugettext as _
-def vote(request, comment_id, vote):
+def vote(request, comment_id, vote, extra_context=None, context_processors=None):
"""
Rate a comment (+1 or -1)
@@ -13,6 +13,7 @@ def vote(request, comment_id, vote):
comment
`comments.comments` object being rated
"""
+ if extra_context is None: extra_context = {}
rating = {'up': 1, 'down': -1}.get(vote, False)
if not rating:
raise Http404, "Invalid vote"
@@ -27,4 +28,5 @@ def vote(request, comment_id, vote):
KarmaScore.objects.vote(request.user.id, comment_id, rating)
# Reload comment to ensure we have up to date karma count
comment = Comment.objects.get(pk=comment_id)
- return render_to_response('comments/karma_vote_accepted.html', {'comment': comment}, context_instance=RequestContext(request))
+ return render_to_response('comments/karma_vote_accepted.html', {'comment': comment},
+ context_instance=RequestContext(request, extra_context, context_processors))
diff --git a/django/contrib/comments/views/userflags.py b/django/contrib/comments/views/userflags.py
index 76f14ef19c..91518dc5dd 100644
--- a/django/contrib/comments/views/userflags.py
+++ b/django/contrib/comments/views/userflags.py
@@ -6,7 +6,7 @@ from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.conf import settings
-def flag(request, comment_id):
+def flag(request, comment_id, extra_context=None, context_processors=None):
"""
Flags a comment. Confirmation on GET, action on POST.
@@ -15,18 +15,22 @@ def flag(request, comment_id):
comment
the flagged `comments.comments` object
"""
+ if extra_context is None: extra_context = {}
comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
if request.POST:
UserFlag.objects.flag(comment, request.user)
return HttpResponseRedirect('%sdone/' % request.path)
- return render_to_response('comments/flag_verify.html', {'comment': comment}, context_instance=RequestContext(request))
+ return render_to_response('comments/flag_verify.html', {'comment': comment},
+ context_instance=RequestContext(request, extra_context, context_processors))
flag = login_required(flag)
-def flag_done(request, comment_id):
+def flag_done(request, comment_id, extra_context=None, context_processors=None):
+ if extra_context is None: extra_context = {}
comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
- return render_to_response('comments/flag_done.html', {'comment': comment}, context_instance=RequestContext(request))
+ return render_to_response('comments/flag_done.html', {'comment': comment},
+ context_instance=RequestContext(request, extra_context, context_processors))
-def delete(request, comment_id):
+def delete(request, comment_id, extra_context=None, context_processors=None):
"""
Deletes a comment. Confirmation on GET, action on POST.
@@ -35,6 +39,7 @@ def delete(request, comment_id):
comment
the flagged `comments.comments` object
"""
+ if extra_context is None: extra_context = {}
comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
if not Comment.objects.user_is_moderator(request.user):
raise Http404
@@ -46,9 +51,12 @@ def delete(request, comment_id):
m = ModeratorDeletion(None, request.user.id, comment.id, None)
m.save()
return HttpResponseRedirect('%sdone/' % request.path)
- return render_to_response('comments/delete_verify.html', {'comment': comment}, context_instance=RequestContext(request))
+ return render_to_response('comments/delete_verify.html', {'comment': comment},
+ context_instance=RequestContext(request, extra_context, context_processors))
delete = login_required(delete)
-def delete_done(request, comment_id):
+def delete_done(request, comment_id, extra_context=None, context_processors=None):
+ if extra_context is None: extra_context = {}
comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID)
- return render_to_response('comments/delete_done.html', {'comment': comment}, context_instance=RequestContext(request))
+ return render_to_response('comments/delete_done.html', {'comment': comment},
+ context_instance=RequestContext(request, extra_context, context_processors))
diff --git a/django/contrib/formtools/preview.py b/django/contrib/formtools/preview.py
index dcb58e85d8..2e4fb92cda 100644
--- a/django/contrib/formtools/preview.py
+++ b/django/contrib/formtools/preview.py
@@ -1,47 +1,5 @@
"""
Formtools Preview application.
-
-This is an abstraction of the following workflow:
-
- "Display an HTML form, force a preview, then do something with the submission."
-
-Given a django.newforms.Form object that you define, this takes care of the
-following:
-
- * Displays the form as HTML on a Web page.
- * Validates the form data once it's submitted via POST.
- * If it's valid, displays a preview page.
- * If it's not valid, redisplays the form with error messages.
- * At the preview page, if the preview confirmation button is pressed, calls
- a hook that you define -- a done() method.
-
-The framework enforces the required preview by passing a shared-secret hash to
-the preview page. If somebody tweaks the form parameters on the preview page,
-the form submission will fail the hash comparison test.
-
-Usage
-=====
-
-Subclass FormPreview and define a done() method:
-
- def done(self, request, cleaned_data):
- # ...
-
-This method takes an HttpRequest object and a dictionary of the form data after
-it has been validated and cleaned. It should return an HttpResponseRedirect.
-
-Then, just instantiate your FormPreview subclass by passing it a Form class,
-and pass that to your URLconf, like so:
-
- (r'^post/$', MyFormPreview(MyForm)),
-
-The FormPreview class has a few other hooks. See the docstrings in the source
-code below.
-
-The framework also uses two templates: 'formtools/preview.html' and
-'formtools/form.html'. You can override these by setting 'preview_template' and
-'form_template' attributes on your FormPreview subclass. See
-django/contrib/formtools/templates for the default templates.
"""
from django.conf import settings
diff --git a/django/contrib/webdesign/templatetags/webdesign.py b/django/contrib/webdesign/templatetags/webdesign.py
index 2370659f1d..1eb1790132 100644
--- a/django/contrib/webdesign/templatetags/webdesign.py
+++ b/django/contrib/webdesign/templatetags/webdesign.py
@@ -62,6 +62,6 @@ def lorem(parser, token):
count = '1'
count = parser.compile_filter(count)
if len(bits) != 1:
- raise TemplateSyntaxError("Incorrect format for %r tag" % tagname)
+ raise template.TemplateSyntaxError("Incorrect format for %r tag" % tagname)
return LoremNode(count, method, common)
lorem = register.tag(lorem)
diff --git a/django/contrib/webdesign/tests.py b/django/contrib/webdesign/tests.py
index eeb1956a01..da9237a43b 100644
--- a/django/contrib/webdesign/tests.py
+++ b/django/contrib/webdesign/tests.py
@@ -7,6 +7,10 @@ u'lorem ipsum dolor sit amet consectetur adipisicing'
>>> paragraphs(1)
['Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.']
+>>> from django.template import loader, Context
+>>> t = loader.get_template_from_string("{% load webdesign %}{% lorem 3 w %}")
+>>> t.render(Context({}))
+u'lorem ipsum dolor'
"""
from django.contrib.webdesign.lorem_ipsum import *
diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index 21737f682f..50495b4ff3 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -142,7 +142,7 @@ def fix_location_header(request, response):
Code constructing response objects is free to insert relative paths and
this function converts them to absolute paths.
"""
- if 'location' in response.headers and http.get_host(request):
+ if 'Location' in response and http.get_host(request):
response['Location'] = request.build_absolute_uri(response['Location'])
return response
diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py
index 7c4bbb3082..f98566be96 100644
--- a/django/core/handlers/modpython.py
+++ b/django/core/handlers/modpython.py
@@ -159,8 +159,8 @@ class ModPythonHandler(BaseHandler):
# Convert our custom HttpResponse object back into the mod_python req.
req.content_type = response['Content-Type']
- for key, value in response.headers.items():
- if key != 'Content-Type':
+ for key, value in response.items():
+ if key != 'content-type':
req.headers_out[str(key)] = str(value)
for c in response.cookies.values():
req.headers_out.add('Set-Cookie', c.output(header=''))
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index 99d400d1bb..6fe24f5d13 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -208,7 +208,7 @@ class WSGIHandler(BaseHandler):
except KeyError:
status_text = 'UNKNOWN STATUS CODE'
status = '%s %s' % (response.status_code, status_text)
- response_headers = [(str(k), str(v)) for k, v in response.headers.items()]
+ response_headers = [(str(k), str(v)) for k, v in response.items()]
for c in response.cookies.values():
response_headers.append(('Set-Cookie', str(c.output(header=''))))
start_response(status, response_headers)
diff --git a/django/core/management/commands/shell.py b/django/core/management/commands/shell.py
index 3baf75c104..96169020e5 100644
--- a/django/core/management/commands/shell.py
+++ b/django/core/management/commands/shell.py
@@ -1,3 +1,4 @@
+import os
from django.core.management.base import NoArgsCommand
from optparse import make_option
@@ -43,4 +44,16 @@ class Command(NoArgsCommand):
import rlcompleter
readline.set_completer(rlcompleter.Completer(imported_objects).complete)
readline.parse_and_bind("tab:complete")
+
+ # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
+ # conventions and get $PYTHONSTARTUP first then import user.
+ if not use_plain:
+ pythonrc = os.environ.get("PYTHONSTARTUP")
+ if pythonrc and os.path.isfile(pythonrc):
+ try:
+ execfile(pythonrc)
+ except NameError:
+ pass
+ # This will import .pythonrc.py as a side-effect
+ import user
code.interact(local=imported_objects)
diff --git a/django/core/management/validation.py b/django/core/management/validation.py
index 6528a34f29..9e004d3d25 100644
--- a/django/core/management/validation.py
+++ b/django/core/management/validation.py
@@ -52,8 +52,7 @@ def get_validation_errors(outfile, app=None):
if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
e.add(opts, '"%s": prepopulate_from should be a list or tuple.' % f.name)
if f.choices:
- if isinstance(f.choices, basestring) or \
- not is_iterable(f.choices):
+ if isinstance(f.choices, basestring) or not is_iterable(f.choices):
e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name)
else:
for c in f.choices:
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index f913b88709..f729629751 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -24,6 +24,12 @@ from MySQLdb.constants import FIELD_TYPE
import types
import re
+# Raise exceptions for database warnings if DEBUG is on
+from django.conf import settings
+if settings.DEBUG:
+ from warnings import filterwarnings
+ filterwarnings("error", category=Database.Warning)
+
DatabaseError = Database.DatabaseError
IntegrityError = Database.IntegrityError
@@ -153,7 +159,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
return False
def _cursor(self, settings):
- from warnings import filterwarnings
if not self._valid_connection():
kwargs = {
'conv': django_conversions,
@@ -175,8 +180,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
kwargs.update(self.options)
self.connection = Database.connect(**kwargs)
cursor = self.connection.cursor()
- if settings.DEBUG:
- filterwarnings("error", category=Database.Warning)
return cursor
def _rollback(self):
diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py
index dbb1d032eb..496fc26306 100644
--- a/django/db/backends/oracle/base.py
+++ b/django/db/backends/oracle/base.py
@@ -290,7 +290,7 @@ class DatabaseOperations(BaseDatabaseOperations):
# string instead of null, but only if the field accepts the
# empty string.
if value is None and isinstance(field, Field) and field.empty_strings_allowed:
- value = ''
+ value = u''
# Convert 1 or 0 to True or False
elif value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)):
value = bool(value)
@@ -354,7 +354,10 @@ class DatabaseOperations(BaseDatabaseOperations):
for sequence_info in sequences:
table_name = sequence_info['table']
seq_name = get_sequence_name(table_name)
- query = _get_sequence_reset_sql() % {'sequence': seq_name, 'table': self.quote_name(table_name)}
+ column_name = self.quote_name(sequence_info['column'] or 'id')
+ query = _get_sequence_reset_sql() % {'sequence': seq_name,
+ 'table': self.quote_name(table_name),
+ 'column': column_name}
sql.append(query)
return sql
else:
@@ -368,13 +371,16 @@ class DatabaseOperations(BaseDatabaseOperations):
for f in model._meta.fields:
if isinstance(f, models.AutoField):
sequence_name = get_sequence_name(model._meta.db_table)
- output.append(query % {'sequence':sequence_name,
- 'table':model._meta.db_table})
+ column_name = self.quote_name(f.db_column or f.name)
+ output.append(query % {'sequence': sequence_name,
+ 'table': model._meta.db_table,
+ 'column': column_name})
break # Only one AutoField is allowed per model, so don't bother continuing.
for f in model._meta.many_to_many:
sequence_name = get_sequence_name(f.m2m_db_table())
- output.append(query % {'sequence':sequence_name,
- 'table':f.m2m_db_table()})
+ output.append(query % {'sequence': sequence_name,
+ 'table': f.m2m_db_table(),
+ 'column': self.quote_name('id')})
return output
def start_transaction_sql(self):
@@ -507,7 +513,7 @@ def _get_sequence_reset_sql():
cval integer;
BEGIN
LOCK TABLE %(table)s IN SHARE MODE;
- SELECT NVL(MAX(id), 0) INTO startvalue FROM %(table)s;
+ SELECT NVL(MAX(%(column)s), 0) INTO startvalue FROM %(table)s;
SELECT %(sequence)s.nextval INTO cval FROM dual;
cval := startvalue - cval;
IF cval != 0 THEN
diff --git a/django/http/__init__.py b/django/http/__init__.py
index 1bb1621d77..1b80237290 100644
--- a/django/http/__init__.py
+++ b/django/http/__init__.py
@@ -246,7 +246,7 @@ class HttpResponse(object):
else:
self._container = [content]
self._is_string = True
- self.headers = {'content-type': content_type}
+ self._headers = {'content-type': content_type}
self.cookies = SimpleCookie()
if status:
self.status_code = status
@@ -254,24 +254,32 @@ class HttpResponse(object):
def __str__(self):
"Full HTTP message, including headers"
return '\n'.join(['%s: %s' % (key, value)
- for key, value in self.headers.items()]) \
+ for key, value in self._headers.items()]) \
+ '\n\n' + self.content
def __setitem__(self, header, value):
- self.headers[header.lower()] = value
+ self._headers[header.lower()] = value
def __delitem__(self, header):
try:
- del self.headers[header.lower()]
+ del self._headers[header.lower()]
except KeyError:
pass
def __getitem__(self, header):
- return self.headers[header.lower()]
+ return self._headers[header.lower()]
def has_header(self, header):
"Case-insensitive check for a header"
- return self.headers.has_key(header.lower())
+ return self._headers.has_key(header.lower())
+
+ __contains__ = has_header
+
+ def items(self):
+ return self._headers.items()
+
+ def get(self, header, alternate):
+ return self._headers.get(header, alternate)
def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None):
self.cookies[key] = value
diff --git a/django/middleware/gzip.py b/django/middleware/gzip.py
index 9b2a5f3d22..7fd0d82419 100644
--- a/django/middleware/gzip.py
+++ b/django/middleware/gzip.py
@@ -20,7 +20,7 @@ class GZipMiddleware(object):
# Avoid gzipping if we've already got a content-encoding or if the
# content-type is Javascript (silly IE...)
- is_js = "javascript" in response.headers.get('Content-Type', '').lower()
+ is_js = "javascript" in response.get('Content-Type', '').lower()
if response.has_header('Content-Encoding') or is_js:
return response
diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py
index 56a2b2634a..2843a33646 100644
--- a/django/shortcuts/__init__.py
+++ b/django/shortcuts/__init__.py
@@ -14,7 +14,7 @@ def render_to_response(*args, **kwargs):
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
- httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype')}
+ httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
load_and_render = render_to_response # For backwards compatibility.
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index 22babfd6c0..1fd6d02c70 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -254,13 +254,20 @@ def escape(value):
escape = stringfilter(escape)
def linebreaks(value):
- "Converts newlines into <p> and <br />s"
+ """
+ Replaces line breaks in plain text with appropriate HTML; a single
+ newline becomes an HTML line break (``<br />``) and a new line
+ followed by a blank line becomes a paragraph break (``</p>``).
+ """
from django.utils.html import linebreaks
return linebreaks(value)
linebreaks = stringfilter(linebreaks)
def linebreaksbr(value):
- "Converts newlines into <br />s"
+ """
+ Converts all newlines in a piece of plain text to HTML line breaks
+ (``<br />``).
+ """
return value.replace('\n', '<br />')
linebreaksbr = stringfilter(linebreaksbr)
diff --git a/django/utils/cache.py b/django/utils/cache.py
index 2753d86949..2494d7839e 100644
--- a/django/utils/cache.py
+++ b/django/utils/cache.py
@@ -42,9 +42,9 @@ def patch_cache_control(response, **kwargs):
def dictitem(s):
t = s.split('=',1)
if len(t) > 1:
- return (t[0].lower().replace('-', '_'), t[1])
+ return (t[0].lower(), t[1])
else:
- return (t[0].lower().replace('-', '_'), True)
+ return (t[0].lower(), True)
def dictvalue(t):
if t[1] is True:
diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py
index 6b6dedfbe9..44c96af147 100644
--- a/django/utils/feedgenerator.py
+++ b/django/utils/feedgenerator.py
@@ -27,7 +27,10 @@ def rfc2822_date(date):
return email.Utils.formatdate(time.mktime(date.timetuple()))
def rfc3339_date(date):
- return date.strftime('%Y-%m-%dT%H:%M:%SZ')
+ if date.tzinfo:
+ return date.strftime('%Y-%m-%dT%H:%M:%S%z')
+ else:
+ return date.strftime('%Y-%m-%dT%H:%M:%SZ')
def get_tag_uri(url, date):
"Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id"