mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
boulder-oracle-sprint: Merged rest of package to trunk [4719]
git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@4722 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
429a542cec
commit
ca343fc0ac
1
AUTHORS
1
AUTHORS
@ -85,6 +85,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Marc Fargas <telenieko@telenieko.com>
|
||||
favo@exoweb.net
|
||||
Eric Floehr <eric@intellovations.com>
|
||||
Jorge Gajon <gajon@gajon.org>
|
||||
gandalf@owca.info
|
||||
Baishampayan Ghose
|
||||
martin.glueck@gmail.com
|
||||
|
@ -81,7 +81,7 @@ def make_messages():
|
||||
src = pythonize_re.sub('\n#', src)
|
||||
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
|
||||
thefile = '%s.py' % file
|
||||
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy -o - "%s"' % (
|
||||
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --from-code UTF-8 -o - "%s"' % (
|
||||
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
|
||||
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
|
||||
msgs = stdout.read()
|
||||
@ -103,7 +103,7 @@ def make_messages():
|
||||
open(os.path.join(dirpath, '%s.py' % file), "wb").write(templatize(src))
|
||||
thefile = '%s.py' % file
|
||||
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
|
||||
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy -o - "%s"' % (
|
||||
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --from-code UTF-8 -o - "%s"' % (
|
||||
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
|
||||
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
|
||||
msgs = stdout.read()
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -168,7 +168,7 @@ def model_detail(request, app_label, model_name):
|
||||
model = m
|
||||
break
|
||||
if model is None:
|
||||
raise Http404, _("Model %r not found in app %r") % (model_name, app_label)
|
||||
raise Http404, _("Model %(name)r not found in app %(label)r") % {'name': model_name, 'label': app_label}
|
||||
|
||||
opts = model._meta
|
||||
|
||||
@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name):
|
||||
if isinstance(field, models.ForeignKey):
|
||||
data_type = related_object_name = field.rel.to.__name__
|
||||
app_label = field.rel.to._meta.app_label
|
||||
verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type)
|
||||
verbose = utils.parse_rst((_("the related `%(label)s.%(type)s` object") % {'label': app_label, 'type': data_type}), 'model', _('model:') + data_type)
|
||||
else:
|
||||
data_type = get_readable_field_data_type(field)
|
||||
verbose = field.verbose_name
|
||||
@ -211,7 +211,7 @@ def model_detail(request, app_label, model_name):
|
||||
|
||||
# Gather related objects
|
||||
for rel in opts.get_all_related_objects():
|
||||
verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name)
|
||||
verbose = _("related `%(label)s.%(name)s` objects") % {'label': rel.opts.app_label, 'name': rel.opts.object_name}
|
||||
accessor = rel.get_accessor_name()
|
||||
fields.append({
|
||||
'name' : "%s.all" % accessor,
|
||||
|
@ -7,6 +7,7 @@ from django.db.models import get_apps, get_models, signals
|
||||
|
||||
def create_contenttypes(app, created_models, verbosity=2):
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
ContentType.objects.clear_cache()
|
||||
app_models = get_models(app)
|
||||
if not app_models:
|
||||
return
|
||||
|
@ -20,6 +20,16 @@ class ContentTypeManager(models.Manager):
|
||||
CONTENT_TYPE_CACHE[key] = ct
|
||||
return ct
|
||||
|
||||
def clear_cache(self):
|
||||
"""
|
||||
Clear out the content-type cache. This needs to happen during database
|
||||
flushes to prevent caching of "stale" content type IDs (see
|
||||
django.contrib.contenttypes.management.create_contenttypes for where
|
||||
this gets called).
|
||||
"""
|
||||
global CONTENT_TYPE_CACHE
|
||||
CONTENT_TYPE_CACHE = {}
|
||||
|
||||
class ContentType(models.Model):
|
||||
name = models.CharField(maxlength=100)
|
||||
app_label = models.CharField(maxlength=100)
|
||||
|
@ -1,3 +1,5 @@
|
||||
from django.utils.translation import ngettext
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django import template
|
||||
import re
|
||||
|
||||
@ -12,9 +14,9 @@ def ordinal(value):
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
return value
|
||||
t = ('th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th')
|
||||
t = (_('th'), _('st'), _('nd'), _('rd'), _('th'), _('th'), _('th'), _('th'), _('th'), _('th'))
|
||||
if value % 100 in (11, 12, 13): # special case
|
||||
return '%dth' % value
|
||||
return "%d%s" % (value, t[0])
|
||||
return '%d%s' % (value, t[value % 10])
|
||||
register.filter(ordinal)
|
||||
|
||||
@ -41,11 +43,14 @@ def intword(value):
|
||||
if value < 1000000:
|
||||
return value
|
||||
if value < 1000000000:
|
||||
return '%.1f million' % (value / 1000000.0)
|
||||
new_value = value / 1000000.0
|
||||
return ngettext('%(value).1f million', '%(value).1f million', new_value) % {'value': new_value}
|
||||
if value < 1000000000000:
|
||||
return '%.1f billion' % (value / 1000000000.0)
|
||||
new_value = value / 1000000000.0
|
||||
return ngettext('%(value).1f billion', '%(value).1f billion', new_value) % {'value': new_value}
|
||||
if value < 1000000000000000:
|
||||
return '%.1f trillion' % (value / 1000000000000.0)
|
||||
new_value = value / 1000000000000.0
|
||||
return ngettext('%(value).1f trillion', '%(value).1f trillion', new_value) % {'value': new_value}
|
||||
return value
|
||||
register.filter(intword)
|
||||
|
||||
@ -60,5 +65,5 @@ def apnumber(value):
|
||||
return value
|
||||
if not 0 < value < 10:
|
||||
return value
|
||||
return ('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine')[value-1]
|
||||
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
|
||||
register.filter(apnumber)
|
||||
|
@ -1463,7 +1463,7 @@ def dump_data(app_labels, format='json', indent=None):
|
||||
for model in get_models(app):
|
||||
objects.extend(model.objects.all())
|
||||
try:
|
||||
print serializers.serialize(format, objects, indent=indent)
|
||||
return serializers.serialize(format, objects, indent=indent)
|
||||
except Exception, e:
|
||||
sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e))
|
||||
dump_data.help_doc = 'Output the contents of the database as a fixture of the given format'
|
||||
@ -1609,7 +1609,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
||||
parser.print_usage_and_exit()
|
||||
elif action == 'dumpdata':
|
||||
try:
|
||||
action_mapping[action](args[1:], options.format, options.indent)
|
||||
print action_mapping[action](args[1:], options.format, options.indent)
|
||||
except IndexError:
|
||||
parser.print_usage_and_exit()
|
||||
elif action in ('startapp', 'startproject'):
|
||||
|
@ -25,6 +25,13 @@ BUILTIN_SERIALIZERS = {
|
||||
"json" : "django.core.serializers.json",
|
||||
}
|
||||
|
||||
# Check for PyYaml and register the serializer if it's available.
|
||||
try:
|
||||
import yaml
|
||||
BUILTIN_SERIALIZERS["yaml"] = "django.core.serializers.pyyaml"
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
_serializers = {}
|
||||
|
||||
def register_serializer(format, serializer_module):
|
||||
|
@ -54,11 +54,7 @@ class Serializer(object):
|
||||
Convert a field's value to a string.
|
||||
"""
|
||||
if isinstance(field, models.DateTimeField):
|
||||
value = getattr(obj, field.name)
|
||||
if value is None:
|
||||
value = ''
|
||||
else:
|
||||
value = value.strftime("%Y-%m-%d %H:%M:%S")
|
||||
value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S")
|
||||
elif isinstance(field, models.FileField):
|
||||
value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
|
||||
else:
|
||||
|
@ -57,7 +57,7 @@ def Deserializer(object_list, **options):
|
||||
for d in object_list:
|
||||
# Look up the model and starting build a dict of data for it.
|
||||
Model = _get_model(d["model"])
|
||||
data = {Model._meta.pk.attname : d["pk"]}
|
||||
data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
|
||||
m2m_data = {}
|
||||
|
||||
# Handle each field
|
||||
@ -70,16 +70,17 @@ def Deserializer(object_list, **options):
|
||||
# Handle M2M relations
|
||||
if field.rel and isinstance(field.rel, models.ManyToManyRel):
|
||||
pks = []
|
||||
m2m_convert = field.rel.to._meta.pk.to_python
|
||||
for pk in field_value:
|
||||
if isinstance(pk, unicode):
|
||||
pks.append(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET)))
|
||||
pks.append(m2m_convert(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET))))
|
||||
else:
|
||||
pks.append(pk)
|
||||
pks.append(m2m_convert(pk))
|
||||
m2m_data[field.name] = pks
|
||||
|
||||
# Handle FK fields
|
||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
||||
data[field.attname] = field_value
|
||||
data[field.attname] = field.rel.to._meta.pk.to_python(field_value)
|
||||
|
||||
# Handle all other fields
|
||||
else:
|
||||
|
36
django/core/serializers/pyyaml.py
Normal file
36
django/core/serializers/pyyaml.py
Normal file
@ -0,0 +1,36 @@
|
||||
"""
|
||||
YAML serializer.
|
||||
|
||||
Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
from django.core.serializers.python import Serializer as PythonSerializer
|
||||
from django.core.serializers.python import Deserializer as PythonDeserializer
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
import yaml
|
||||
|
||||
class Serializer(PythonSerializer):
|
||||
"""
|
||||
Convert a queryset to JSON.
|
||||
"""
|
||||
def end_serialization(self):
|
||||
yaml.dump(self.objects, self.stream, **self.options)
|
||||
|
||||
def getvalue(self):
|
||||
return self.stream.getvalue()
|
||||
|
||||
def Deserializer(stream_or_string, **options):
|
||||
"""
|
||||
Deserialize a stream or string of JSON data.
|
||||
"""
|
||||
if isinstance(stream_or_string, basestring):
|
||||
stream = StringIO(stream_or_string)
|
||||
else:
|
||||
stream = stream_or_string
|
||||
for obj in PythonDeserializer(yaml.load(stream)):
|
||||
yield obj
|
||||
|
@ -57,10 +57,12 @@ class Serializer(base.Serializer):
|
||||
})
|
||||
|
||||
# Get a "string version" of the object's data (this is handled by the
|
||||
# serializer base class). None is handled specially.
|
||||
# serializer base class).
|
||||
if getattr(obj, field.name) is not None:
|
||||
value = self.get_string_value(obj, field)
|
||||
if value is not None:
|
||||
self.xml.characters(str(value))
|
||||
else:
|
||||
self.xml.addQuickElement("None")
|
||||
|
||||
self.xml.endElement("field")
|
||||
|
||||
@ -127,7 +129,8 @@ class Deserializer(base.Deserializer):
|
||||
pk = node.getAttribute("pk")
|
||||
if not pk:
|
||||
raise base.DeserializationError("<object> node is missing the 'pk' attribute")
|
||||
data = {Model._meta.pk.name : pk}
|
||||
|
||||
data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)}
|
||||
|
||||
# Also start building a dict of m2m data (this is saved as
|
||||
# {m2m_accessor_attribute : [list_of_related_objects]})
|
||||
@ -148,9 +151,12 @@ class Deserializer(base.Deserializer):
|
||||
|
||||
# As is usually the case, relation fields get the special treatment.
|
||||
if field.rel and isinstance(field.rel, models.ManyToManyRel):
|
||||
m2m_data[field.name] = self._handle_m2m_field_node(field_node)
|
||||
m2m_data[field.name] = self._handle_m2m_field_node(field_node, field)
|
||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
||||
data[field.attname] = self._handle_fk_field_node(field_node)
|
||||
data[field.attname] = self._handle_fk_field_node(field_node, field)
|
||||
else:
|
||||
if len(field_node.childNodes) == 1 and field_node.childNodes[0].nodeName == 'None':
|
||||
value = None
|
||||
else:
|
||||
value = field.to_python(getInnerText(field_node).strip().encode(self.encoding))
|
||||
data[field.name] = value
|
||||
@ -158,7 +164,7 @@ class Deserializer(base.Deserializer):
|
||||
# Return a DeserializedObject so that the m2m data has a place to live.
|
||||
return base.DeserializedObject(Model(**data), m2m_data)
|
||||
|
||||
def _handle_fk_field_node(self, node):
|
||||
def _handle_fk_field_node(self, node, field):
|
||||
"""
|
||||
Handle a <field> node for a ForeignKey
|
||||
"""
|
||||
@ -166,13 +172,16 @@ class Deserializer(base.Deserializer):
|
||||
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
|
||||
return None
|
||||
else:
|
||||
return getInnerText(node).strip().encode(self.encoding)
|
||||
return field.rel.to._meta.pk.to_python(
|
||||
getInnerText(node).strip().encode(self.encoding))
|
||||
|
||||
def _handle_m2m_field_node(self, node):
|
||||
def _handle_m2m_field_node(self, node, field):
|
||||
"""
|
||||
Handle a <field> node for a ManyToManyField
|
||||
"""
|
||||
return [c.getAttribute("pk").encode(self.encoding) for c in node.getElementsByTagName("object")]
|
||||
return [field.rel.to._meta.pk.to_python(
|
||||
c.getAttribute("pk").encode(self.encoding))
|
||||
for c in node.getElementsByTagName("object")]
|
||||
|
||||
def _get_model_from_node(self, node, attr):
|
||||
"""
|
||||
|
@ -140,7 +140,8 @@ def _isValidDate(date_string):
|
||||
try:
|
||||
date(year, month, day)
|
||||
except ValueError, e:
|
||||
raise ValidationError, gettext('Invalid date: %s.' % e)
|
||||
msg = gettext('Invalid date: %s') % gettext(str(e))
|
||||
raise ValidationError, msg
|
||||
|
||||
def isValidANSIDate(field_data, all_data):
|
||||
if not ansi_date_re.search(field_data):
|
||||
@ -363,7 +364,7 @@ class NumberIsInRange(object):
|
||||
self.lower, self.upper = lower, upper
|
||||
if not error_message:
|
||||
if lower and upper:
|
||||
self.error_message = gettext("This value must be between %s and %s.") % (lower, upper)
|
||||
self.error_message = gettext("This value must be between %(lower)s and %(upper)s.") % {'lower': lower, 'upper': upper}
|
||||
elif lower:
|
||||
self.error_message = gettext("This value must be at least %s.") % lower
|
||||
elif upper:
|
||||
|
@ -762,6 +762,13 @@ class NullBooleanField(Field):
|
||||
kwargs['null'] = True
|
||||
Field.__init__(self, *args, **kwargs)
|
||||
|
||||
def to_python(self, value):
|
||||
if value in (None, True, False): return value
|
||||
if value in ('None'): return None
|
||||
if value in ('t', 'True', '1'): return True
|
||||
if value in ('f', 'False', '0'): return False
|
||||
raise validators.ValidationError, gettext("This value must be either None, True or False.")
|
||||
|
||||
def get_manipulator_field_objs(self):
|
||||
return [oldforms.NullBooleanField]
|
||||
|
||||
|
@ -16,7 +16,7 @@ class RelatedObject(object):
|
||||
self.opts = model._meta
|
||||
self.field = field
|
||||
self.edit_inline = field.rel.edit_inline
|
||||
self.name = '%s_%s' % (self.opts.app_label, self.opts.module_name)
|
||||
self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
|
||||
self.var_name = self.opts.object_name.lower()
|
||||
|
||||
def flatten_data(self, follow, obj=None):
|
||||
|
@ -130,7 +130,9 @@ class FormWrapper(object):
|
||||
if self.edit_inline:
|
||||
self.fill_inline_collections()
|
||||
for inline_collection in self._inline_collections:
|
||||
if inline_collection.name == key:
|
||||
# The 'orig_name' comparison is for backwards compatibility
|
||||
# with hand-crafted forms.
|
||||
if inline_collection.name == key or (':' not in key and inline_collection.orig_name == key):
|
||||
return inline_collection
|
||||
raise KeyError, "Could not find Formfield or InlineObjectCollection named %r" % key
|
||||
|
||||
@ -226,6 +228,9 @@ class InlineObjectCollection(object):
|
||||
self.errors = errors
|
||||
self._collections = None
|
||||
self.name = rel_obj.name
|
||||
# This is the name used prior to fixing #1839. Needs for backwards
|
||||
# compatibility.
|
||||
self.orig_name = rel_obj.opts.module_name
|
||||
|
||||
def __len__(self):
|
||||
self.fill()
|
||||
|
@ -70,14 +70,15 @@ def floatformat(text, arg=-1):
|
||||
With a negative numeric argument, it will display that many decimal
|
||||
places -- but only if there's places to be displayed.
|
||||
Examples:
|
||||
num1 = 34.23234
|
||||
num2 = 34.00000
|
||||
num1|floatformat results in 34.2
|
||||
num2|floatformat is 34
|
||||
num1|floatformat:3 is 34.232
|
||||
num2|floatformat:3 is 34.000
|
||||
num1|floatformat:-3 is 34.232
|
||||
num2|floatformat:-3 is 34
|
||||
|
||||
* num1 = 34.23234
|
||||
* num2 = 34.00000
|
||||
* num1|floatformat results in 34.2
|
||||
* num2|floatformat is 34
|
||||
* num1|floatformat:3 is 34.232
|
||||
* num2|floatformat:3 is 34.000
|
||||
* num1|floatformat:-3 is 34.232
|
||||
* num2|floatformat:-3 is 34
|
||||
"""
|
||||
try:
|
||||
f = float(text)
|
||||
|
@ -435,6 +435,15 @@ def cycle(parser, token):
|
||||
cycle = register.tag(cycle)
|
||||
|
||||
def debug(parser, token):
|
||||
"""
|
||||
Output a whole load of debugging information, including the current context and imported modules.
|
||||
|
||||
Sample usage::
|
||||
|
||||
<pre>
|
||||
{% debug %}
|
||||
</pre>
|
||||
"""
|
||||
return DebugNode()
|
||||
debug = register.tag(debug)
|
||||
|
||||
@ -538,21 +547,6 @@ def do_for(parser, token):
|
||||
do_for = register.tag("for", do_for)
|
||||
|
||||
def do_ifequal(parser, token, negate):
|
||||
"""
|
||||
Output the contents of the block if the two arguments equal/don't equal each other.
|
||||
|
||||
Examples::
|
||||
|
||||
{% ifequal user.id comment.user_id %}
|
||||
...
|
||||
{% endifequal %}
|
||||
|
||||
{% ifnotequal user.id comment.user_id %}
|
||||
...
|
||||
{% else %}
|
||||
...
|
||||
{% endifnotequal %}
|
||||
"""
|
||||
bits = list(token.split_contents())
|
||||
if len(bits) != 3:
|
||||
raise TemplateSyntaxError, "%r takes two arguments" % bits[0]
|
||||
@ -568,11 +562,27 @@ def do_ifequal(parser, token, negate):
|
||||
|
||||
#@register.tag
|
||||
def ifequal(parser, token):
|
||||
"""
|
||||
Output the contents of the block if the two arguments equal each other.
|
||||
|
||||
Examples::
|
||||
|
||||
{% ifequal user.id comment.user_id %}
|
||||
...
|
||||
{% endifequal %}
|
||||
|
||||
{% ifnotequal user.id comment.user_id %}
|
||||
...
|
||||
{% else %}
|
||||
...
|
||||
{% endifnotequal %}
|
||||
"""
|
||||
return do_ifequal(parser, token, False)
|
||||
ifequal = register.tag(ifequal)
|
||||
|
||||
#@register.tag
|
||||
def ifnotequal(parser, token):
|
||||
"""Output the contents of the block if the two arguments are not equal. See ifequal"""
|
||||
return do_ifequal(parser, token, True)
|
||||
ifnotequal = register.tag(ifnotequal)
|
||||
|
||||
@ -889,8 +899,9 @@ templatetag = register.tag(templatetag)
|
||||
|
||||
def url(parser, token):
|
||||
"""
|
||||
Returns an absolute URL matching given view with its parameters. This is a
|
||||
way to define links that aren't tied to a particular url configuration:
|
||||
Returns an absolute URL matching given view with its parameters.
|
||||
|
||||
This is a way to define links that aren't tied to a particular url configuration::
|
||||
|
||||
{% url path.to.some_view arg1,arg2,name1=value1 %}
|
||||
|
||||
@ -901,16 +912,16 @@ def url(parser, token):
|
||||
URL. All arguments for the URL should be present.
|
||||
|
||||
For example if you have a view ``app_name.client`` taking client's id and
|
||||
the corresponding line in a urlconf looks like this:
|
||||
the corresponding line in a urlconf looks like this::
|
||||
|
||||
('^client/(\d+)/$', 'app_name.client')
|
||||
|
||||
and this app's urlconf is included into the project's urlconf under some
|
||||
path:
|
||||
path::
|
||||
|
||||
('^clients/', include('project_name.app_name.urls'))
|
||||
|
||||
then in a template you can create a link for a certain client like this:
|
||||
then in a template you can create a link for a certain client like this::
|
||||
|
||||
{% url app_name.client client.id %}
|
||||
|
||||
|
@ -13,6 +13,7 @@ Usage:
|
||||
|
||||
from django.utils.dates import MONTHS, MONTHS_3, MONTHS_AP, WEEKDAYS
|
||||
from django.utils.tzinfo import LocalTimezone
|
||||
from django.utils.translation import gettext as _
|
||||
from calendar import isleap, monthrange
|
||||
import re, time
|
||||
|
||||
@ -36,14 +37,14 @@ class TimeFormat(Formatter):
|
||||
def a(self):
|
||||
"'a.m.' or 'p.m.'"
|
||||
if self.data.hour > 11:
|
||||
return 'p.m.'
|
||||
return 'a.m.'
|
||||
return _('p.m.')
|
||||
return _('a.m.')
|
||||
|
||||
def A(self):
|
||||
"'AM' or 'PM'"
|
||||
if self.data.hour > 11:
|
||||
return 'PM'
|
||||
return 'AM'
|
||||
return _('PM')
|
||||
return _('AM')
|
||||
|
||||
def B(self):
|
||||
"Swatch Internet time"
|
||||
@ -91,9 +92,9 @@ class TimeFormat(Formatter):
|
||||
Proprietary extension.
|
||||
"""
|
||||
if self.data.minute == 0 and self.data.hour == 0:
|
||||
return 'midnight'
|
||||
return _('midnight')
|
||||
if self.data.minute == 0 and self.data.hour == 12:
|
||||
return 'noon'
|
||||
return _('noon')
|
||||
return '%s %s' % (self.f(), self.a())
|
||||
|
||||
def s(self):
|
||||
|
@ -9,16 +9,16 @@ def set_language(request):
|
||||
"""
|
||||
Redirect to a given url while setting the chosen language in the
|
||||
session or cookie. The url and the language code need to be
|
||||
specified in the GET paramters.
|
||||
specified in the GET parameters.
|
||||
"""
|
||||
lang_code = request.GET['language']
|
||||
lang_code = request.GET.get('language', None)
|
||||
next = request.GET.get('next', None)
|
||||
if not next:
|
||||
next = request.META.get('HTTP_REFERER', None)
|
||||
if not next:
|
||||
next = '/'
|
||||
response = http.HttpResponseRedirect(next)
|
||||
if check_for_language(lang_code):
|
||||
if lang_code and check_for_language(lang_code):
|
||||
if hasattr(request, 'session'):
|
||||
request.session['django_language'] = lang_code
|
||||
else:
|
||||
|
@ -304,3 +304,14 @@ If you have access to a command shell on a Unix system, you can accomplish this
|
||||
easily by using the ``touch`` command::
|
||||
|
||||
touch mysite.fcgi
|
||||
|
||||
Serving admin media files
|
||||
=========================
|
||||
|
||||
Regardless of the server and configuration you eventually decide to use, you will
|
||||
also need to give some thought to how to serve the admin media files. The
|
||||
advice given in the modpython_ documentation is also applicable in the setups
|
||||
detailed above.
|
||||
|
||||
.. _modpython: ../modpython/#serving-the-admin-files
|
||||
|
||||
|
@ -417,6 +417,27 @@ Here's a simple function that might drive the above form::
|
||||
form = forms.FormWrapper(manipulator, new_data, errors)
|
||||
return render_to_response('contact_form.html', {'form': form})
|
||||
|
||||
Implementing ``flatten_data`` for custom manipulators
|
||||
------------------------------------------------------
|
||||
|
||||
It is possible (although rarely needed) to replace the default automatically
|
||||
created manipulators on a model with your own custom manipulators. If you do
|
||||
this and you are intending to use those models in generic views, you should
|
||||
also define a ``flatten_data`` method in any ``ChangeManipulator`` replacement.
|
||||
This should act like the default ``flatten_data`` and return a dictionary
|
||||
mapping field names to their values, like so::
|
||||
|
||||
def flatten_data(self):
|
||||
obj = self.original_object
|
||||
return dict(
|
||||
from = obj.from,
|
||||
subject = obj.subject,
|
||||
...
|
||||
)
|
||||
|
||||
In this way, your new change manipulator will act exactly like the default
|
||||
version.
|
||||
|
||||
``FileField`` and ``ImageField`` special cases
|
||||
==============================================
|
||||
|
||||
|
@ -282,6 +282,17 @@ How to create language files
|
||||
Once you've tagged your strings for later translation, you need to write (or
|
||||
obtain) the language translations themselves. Here's how that works.
|
||||
|
||||
.. admonition:: Locale restrictions
|
||||
|
||||
Django does not support localising your application into a locale for
|
||||
which Django itself has not been translated -- it will ignore your
|
||||
translation files. If you were to try this and Django supported it, you
|
||||
would inevitably see a mixture of translated strings (from your
|
||||
application) and English strings (from Django itself). If you are wanting
|
||||
to support a locale for your application that is not already part of
|
||||
Django, you will need to make at least a minimal translation of the Django
|
||||
core.
|
||||
|
||||
Message files
|
||||
-------------
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user