1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

newforms-admin: Merged to [5595]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@5596 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-07-03 16:03:51 +00:00
parent 160dac766c
commit 7ed1a91968
10 changed files with 99 additions and 53 deletions

View File

@ -235,6 +235,7 @@ answer newbie questions, and generally made Django that much better:
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/> Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
torne-django@wolfpuppy.org.uk torne-django@wolfpuppy.org.uk
Karen Tracey <graybark@bellsouth.net> Karen Tracey <graybark@bellsouth.net>
tstromberg@google.com
Makoto Tsuyuki <mtsuyuki@gmail.com> Makoto Tsuyuki <mtsuyuki@gmail.com>
tt@gurgle.no tt@gurgle.no
Amit Upadhyay Amit Upadhyay

View File

@ -267,7 +267,7 @@ class AnonymousUser(object):
pass pass
def __str__(self): def __str__(self):
return _('AnonymousUser') return 'AnonymousUser'
def __eq__(self, other): def __eq__(self, other):
return isinstance(other, self.__class__) return isinstance(other, self.__class__)

View File

@ -37,6 +37,7 @@ class SessionWrapper(object):
return self._session.get(key, default) return self._session.get(key, default)
def pop(self, key, *args): def pop(self, key, *args):
self.modified = self.modified or key in self._session
return self._session.pop(key, *args) return self._session.pop(key, *args)
def set_test_cookie(self): def set_test_cookie(self):

View File

@ -5,8 +5,24 @@ Inject data into the session cache.
>>> s._session_cache = {} >>> s._session_cache = {}
>>> s._session_cache['some key'] = 'exists' >>> s._session_cache['some key'] = 'exists'
>>> s.accessed
False
>>> s.modified
False
>>> s.pop('non existant key', 'does not exist')
'does not exist'
>>> s.accessed
True
>>> s.modified
False
>>> s.pop('some key') >>> s.pop('some key')
'exists' 'exists'
>>> s.accessed
True
>>> s.modified
True
>>> s.pop('some key', 'does not exist') >>> s.pop('some key', 'does not exist')
'does not exist' 'does not exist'

View File

@ -62,22 +62,23 @@ def make_msgid(idstring=None):
class BadHeaderError(ValueError): class BadHeaderError(ValueError):
pass pass
class SafeHeaderMixin(object): class SafeMIMEText(MIMEText):
def __setitem__(self, name, val): def __setitem__(self, name, val):
"Forbids multi-line headers, to prevent header injection." "Forbids multi-line headers, to prevent header injection."
if '\n' in val or '\r' in val: if '\n' in val or '\r' in val:
raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name) raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name)
if name == "Subject": if name == "Subject":
val = Header(val, settings.DEFAULT_CHARSET) val = Header(val, settings.DEFAULT_CHARSET)
# Note: using super() here is safe; any __setitem__ overrides must use MIMEText.__setitem__(self, name, val)
# the same argument signature.
super(SafeHeaderMixin, self).__setitem__(name, val)
class SafeMIMEText(MIMEText, SafeHeaderMixin): class SafeMIMEMultipart(MIMEMultipart):
pass def __setitem__(self, name, val):
"Forbids multi-line headers, to prevent header injection."
class SafeMIMEMultipart(MIMEMultipart, SafeHeaderMixin): if '\n' in val or '\r' in val:
pass raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name)
if name == "Subject":
val = Header(val, settings.DEFAULT_CHARSET)
MIMEMultipart.__setitem__(self, name, val)
class SMTPConnection(object): class SMTPConnection(object):
""" """

View File

@ -832,9 +832,15 @@ def startproject(project_name, directory):
sys.stderr.write(style.ERROR("Error: '%r' conflicts with the name of an existing Python module and cannot be used as a project name. Please try another name.\n" % project_name)) sys.stderr.write(style.ERROR("Error: '%r' conflicts with the name of an existing Python module and cannot be used as a project name. Please try another name.\n" % project_name))
sys.exit(1) sys.exit(1)
_start_helper('project', project_name, directory) _start_helper('project', project_name, directory)
# Create a random SECRET_KEY hash, and put it in the main settings. # Create a random SECRET_KEY hash, and put it in the main settings.
main_settings_file = os.path.join(directory, project_name, 'settings.py') main_settings_file = os.path.join(directory, project_name, 'settings.py')
settings_contents = open(main_settings_file, 'r').read() settings_contents = open(main_settings_file, 'r').read()
# If settings.py was copied from a read-only source, make it writeable.
if not os.access(main_settings_file, os.W_OK):
os.chmod(main_settings_file, 0600)
fp = open(main_settings_file, 'w') fp = open(main_settings_file, 'w')
secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)]) secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
settings_contents = re.sub(r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents) settings_contents = re.sub(r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents)

View File

@ -482,17 +482,18 @@ class ComboField(Field):
class MultiValueField(Field): class MultiValueField(Field):
""" """
A Field that is composed of multiple Fields. A Field that aggregates the logic of multiple Fields.
Its clean() method takes a "decompressed" list of values. Each value in Its clean() method takes a "decompressed" list of values, which are then
cleaned into a single value according to self.fields. Each value in
this list is cleaned by the corresponding field -- the first value is this list is cleaned by the corresponding field -- the first value is
cleaned by the first field, the second value is cleaned by the second cleaned by the first field, the second value is cleaned by the second
field, etc. Once all fields are cleaned, the list of clean values is field, etc. Once all fields are cleaned, the list of clean values is
"compressed" into a single value. "compressed" into a single value.
Subclasses should implement compress(), which specifies how a list of Subclasses should not have to implement clean(). Instead, they must
valid values should be converted to a single value. Subclasses should not implement compress(), which takes a list of valid values and returns a
have to implement clean(). "compressed" version of those values -- a single value.
You'll probably want to use this with MultiWidget. You'll probably want to use this with MultiWidget.
""" """

View File

@ -304,19 +304,28 @@ class MultiWidget(Widget):
""" """
A widget that is composed of multiple widgets. A widget that is composed of multiple widgets.
Its render() method takes a "decompressed" list of values, not a single Its render() method is different than other widgets', because it has to
value. Each value in this list is rendered in the corresponding widget -- figure out how to split a single value for display in multiple widgets.
the first value is rendered in the first widget, the second value is The ``value`` argument can be one of two things:
rendered in the second widget, etc.
Subclasses should implement decompress(), which specifies how a single * A list.
value should be converted to a list of values. Subclasses should not * A normal value (e.g., a string) that has been "compressed" from
have to implement clean(). a list of values.
In the second case -- i.e., if the value is NOT a list -- render() will
first "decompress" the value into a list before rendering it. It does so by
calling the decompress() method, which MultiWidget subclasses must
implement. This method takes a single "compressed" value and returns a
list.
When render() does its HTML rendering, each value in the list is rendered
with the corresponding widget -- the first value is rendered in the first
widget, the second value is rendered in the second widget, etc.
Subclasses may implement format_output(), which takes the list of rendered Subclasses may implement format_output(), which takes the list of rendered
widgets and returns HTML that formats them any way you'd like. widgets and returns a string of HTML that formats them any way you'd like.
You'll probably want to use this with MultiValueField. You'll probably want to use this class with MultiValueField.
""" """
def __init__(self, widgets, attrs=None): def __init__(self, widgets, attrs=None):
self.widgets = [isinstance(w, type) and w() or w for w in widgets] self.widgets = [isinstance(w, type) and w() or w for w in widgets]
@ -351,6 +360,13 @@ class MultiWidget(Widget):
return [widget.value_from_datadict(data, name + '_%s' % i) for i, widget in enumerate(self.widgets)] return [widget.value_from_datadict(data, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
def format_output(self, rendered_widgets): def format_output(self, rendered_widgets):
"""
Given a list of rendered widgets (as strings), returns a Unicode string
representing the HTML for the whole lot.
This hook allows you to format the HTML design of the widgets, if
needed.
"""
return u''.join(rendered_widgets) return u''.join(rendered_widgets)
def decompress(self, value): def decompress(self, value):

View File

@ -21,7 +21,7 @@ def shortcut(request, content_type_id, object_id):
# if necessary. # if necessary.
# If the object actually defines a domain, we're done. # If the object actually defines a domain, we're done.
if absurl.startswith('http://'): if absurl.startswith('http://') or absurl.startswith('https://'):
return http.HttpResponseRedirect(absurl) return http.HttpResponseRedirect(absurl)
object_domain = None object_domain = None
@ -61,7 +61,8 @@ def shortcut(request, content_type_id, object_id):
# If all that malarkey found an object domain, use it; otherwise fall back # If all that malarkey found an object domain, use it; otherwise fall back
# to whatever get_absolute_url() returned. # to whatever get_absolute_url() returned.
if object_domain is not None: if object_domain is not None:
return http.HttpResponseRedirect('http://%s%s' % (object_domain, absurl)) protocol = request.is_secure() and 'https' or 'http'
return http.HttpResponseRedirect('%s://%s%s' % (protocol, object_domain, absurl))
else: else:
return http.HttpResponseRedirect(absurl) return http.HttpResponseRedirect(absurl)

View File

@ -5,6 +5,7 @@ This demonstrates features of the database API.
""" """
from django.db import models from django.db import models
from django.conf import settings
class Article(models.Model): class Article(models.Model):
headline = models.CharField(maxlength=100) headline = models.CharField(maxlength=100)
@ -263,14 +264,14 @@ TypeError: Cannot resolve keyword 'headline__starts' into field. Choices are: id
>>> a3.save() >>> a3.save()
>>> a4 = Article(pub_date=now, headline='fooo') >>> a4 = Article(pub_date=now, headline='fooo')
>>> a4.save() >>> a4.save()
>>> a5 = Article(pub_date=now, headline='Foo') >>> a5 = Article(pub_date=now, headline='hey-Foo')
>>> a5.save() >>> a5.save()
# zero-or-more # zero-or-more
>>> Article.objects.filter(headline__regex=r'fo*') >>> Article.objects.filter(headline__regex=r'fo*')
[<Article: f>, <Article: fo>, <Article: foo>, <Article: fooo>] [<Article: f>, <Article: fo>, <Article: foo>, <Article: fooo>]
>>> Article.objects.filter(headline__iregex=r'fo*') >>> Article.objects.filter(headline__iregex=r'fo*')
[<Article: Foo>, <Article: f>, <Article: fo>, <Article: foo>, <Article: fooo>] [<Article: f>, <Article: fo>, <Article: foo>, <Article: fooo>, <Article: hey-Foo>]
# one-or-more # one-or-more
>>> Article.objects.filter(headline__regex=r'fo+') >>> Article.objects.filter(headline__regex=r'fo+')
@ -283,39 +284,39 @@ TypeError: Cannot resolve keyword 'headline__starts' into field. Choices are: id
# and some more: # and some more:
>>> a6 = Article(pub_date=now, headline='bar') >>> a6 = Article(pub_date=now, headline='bar')
>>> a6.save() >>> a6.save()
>>> a7 = Article(pub_date=now, headline='Bar') >>> a7 = Article(pub_date=now, headline='AbBa')
>>> a7.save() >>> a7.save()
>>> a8 = Article(pub_date=now, headline='baz') >>> a8 = Article(pub_date=now, headline='baz')
>>> a8.save() >>> a8.save()
>>> a9 = Article(pub_date=now, headline='baZ') >>> a9 = Article(pub_date=now, headline='baxZ')
>>> a9.save() >>> a9.save()
# leading anchor # leading anchor
>>> Article.objects.filter(headline__regex=r'^b') >>> Article.objects.filter(headline__regex=r'^b')
[<Article: baZ>, <Article: bar>, <Article: baz>] [<Article: bar>, <Article: baxZ>, <Article: baz>]
>>> Article.objects.filter(headline__iregex=r'^b') >>> Article.objects.filter(headline__iregex=r'^a')
[<Article: Bar>, <Article: baZ>, <Article: bar>, <Article: baz>] [<Article: AbBa>]
# trailing anchor # trailing anchor
>>> Article.objects.filter(headline__regex=r'z$') >>> Article.objects.filter(headline__regex=r'z$')
[<Article: baz>] [<Article: baz>]
>>> Article.objects.filter(headline__iregex=r'z$') >>> Article.objects.filter(headline__iregex=r'z$')
[<Article: baZ>, <Article: baz>] [<Article: baxZ>, <Article: baz>]
# character sets # character sets
>>> Article.objects.filter(headline__regex=r'ba[rz]') >>> Article.objects.filter(headline__regex=r'ba[rz]')
[<Article: bar>, <Article: baz>] [<Article: bar>, <Article: baz>]
>>> Article.objects.filter(headline__regex=r'ba[RZ]') >>> Article.objects.filter(headline__regex=r'ba.[RxZ]')
[<Article: baZ>] [<Article: baxZ>]
>>> Article.objects.filter(headline__iregex=r'ba[RZ]') >>> Article.objects.filter(headline__iregex=r'ba[RxZ]')
[<Article: Bar>, <Article: baZ>, <Article: bar>, <Article: baz>] [<Article: bar>, <Article: baxZ>, <Article: baz>]
# and yet more: # and yet more:
>>> a10 = Article(pub_date=now, headline='foobar') >>> a10 = Article(pub_date=now, headline='foobar')
>>> a10.save() >>> a10.save()
>>> a11 = Article(pub_date=now, headline='foobaz') >>> a11 = Article(pub_date=now, headline='foobaz')
>>> a11.save() >>> a11.save()
>>> a12 = Article(pub_date=now, headline='FooBarBaz') >>> a12 = Article(pub_date=now, headline='ooF')
>>> a12.save() >>> a12.save()
>>> a13 = Article(pub_date=now, headline='foobarbaz') >>> a13 = Article(pub_date=now, headline='foobarbaz')
>>> a13.save() >>> a13.save()
@ -323,26 +324,28 @@ TypeError: Cannot resolve keyword 'headline__starts' into field. Choices are: id
>>> a14.save() >>> a14.save()
>>> a15 = Article(pub_date=now, headline='barfoobaz') >>> a15 = Article(pub_date=now, headline='barfoobaz')
>>> a15.save() >>> a15.save()
>>> a16 = Article(pub_date=now, headline='BAZBARFOO') >>> a16 = Article(pub_date=now, headline='bazbaRFOO')
>>> a16.save() >>> a16.save()
# alternation # alternation
>>> Article.objects.filter(headline__regex=r'foo(bar|baz)') >>> Article.objects.filter(headline__regex=r'oo(f|b)')
[<Article: barfoobaz>, <Article: foobar>, <Article: foobarbaz>, <Article: foobaz>] [<Article: barfoobaz>, <Article: foobar>, <Article: foobarbaz>, <Article: foobaz>]
>>> Article.objects.filter(headline__iregex=r'foo(bar|baz)') >>> Article.objects.filter(headline__iregex=r'oo(f|b)')
[<Article: FooBarBaz>, <Article: barfoobaz>, <Article: foobar>, <Article: foobarbaz>, <Article: foobaz>] [<Article: barfoobaz>, <Article: foobar>, <Article: foobarbaz>, <Article: foobaz>, <Article: ooF>]
>>> Article.objects.filter(headline__regex=r'^foo(bar|baz)') >>> Article.objects.filter(headline__regex=r'^foo(f|b)')
[<Article: foobar>, <Article: foobarbaz>, <Article: foobaz>] [<Article: foobar>, <Article: foobarbaz>, <Article: foobaz>]
# greedy matching # greedy matching
>>> Article.objects.filter(headline__regex=r'f.*z') >>> Article.objects.filter(headline__regex=r'b.*az')
[<Article: barfoobaz>, <Article: foobarbaz>, <Article: foobaz>, <Article: zoocarfaz>] [<Article: barfoobaz>, <Article: baz>, <Article: bazbaRFOO>, <Article: foobarbaz>, <Article: foobaz>]
>>> Article.objects.filter(headline__iregex=r'f.*z') >>> Article.objects.filter(headline__iregex=r'b.*ar')
[<Article: FooBarBaz>, <Article: barfoobaz>, <Article: foobarbaz>, <Article: foobaz>, <Article: zoocarfaz>] [<Article: bar>, <Article: barfoobaz>, <Article: bazbaRFOO>, <Article: foobar>, <Article: foobarbaz>]
"""}
if settings.DATABASE_ENGINE not in ('mysql', 'mysql_old'):
__test__['API_TESTS'] += r"""
# grouping and backreferences # grouping and backreferences
>>> Article.objects.filter(headline__regex=r'b(.).*b\1') >>> Article.objects.filter(headline__regex=r'b(.).*b\1')
[<Article: barfoobaz>, <Article: foobarbaz>] [<Article: barfoobaz>, <Article: bazbaRFOO>, <Article: foobarbaz>]
>>> Article.objects.filter(headline__iregex=r'b(.).*b\1') """
[<Article: BAZBARFOO>, <Article: FooBarBaz>, <Article: barfoobaz>, <Article: foobarbaz>]
"""}