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:
parent
160dac766c
commit
7ed1a91968
1
AUTHORS
1
AUTHORS
@ -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
|
||||||
|
@ -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__)
|
||||||
|
@ -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):
|
||||||
|
@ -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'
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
"""
|
"""
|
||||||
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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>]
|
|
||||||
"""}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user