1
0
mirror of https://github.com/django/django.git synced 2025-07-05 10:19:20 +00:00

[multi-db] Merge trunk to [3302]

git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3303 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jason Pellerin 2006-07-09 17:11:34 +00:00
parent 60947322a5
commit ef1a9eeb64
42 changed files with 406 additions and 227 deletions

View File

@ -54,6 +54,7 @@ answer newbie questions, and generally made Django that much better:
Jason Davies (Esaj) <http://www.jasondavies.com/>
Alex Dedul
deric@monowerks.com
dne@mayonnaise.net
Jeremy Dunck <http://dunck.us/>
Clint Ecker
gandalf@owca.info

View File

@ -116,7 +116,7 @@ class UserSettingsHolder(object):
"""
Holder for user configured settings.
"""
# SETTINGS_MODULE does not really make sense in the manually configured
# SETTINGS_MODULE doesn't make much sense in the manually configured
# (standalone) case.
SETTINGS_MODULE = None
@ -135,6 +135,13 @@ class UserSettingsHolder(object):
settings = LazySettings()
# install the translation machinery so that it is available
from django.utils import translation
translation.install()
# This function replaces itself with django.utils.translation.gettext() the
# first time it's run. This is necessary because the import of
# django.utils.translation requires a working settings module, and loading it
# from within this file would cause a circular import.
def first_time_gettext(*args):
from django.utils.translation import gettext
__builtins__['_'] = gettext
return gettext(*args)
__builtins__['_'] = first_time_gettext

View File

@ -1,7 +1,9 @@
# Default Django settings. Override these with settings in the module
# pointed-to by the DJANGO_SETTINGS_MODULE environment variable.
from django.utils.translation import gettext_lazy as _
# This is defined here as a do-nothing function because we can't import
# django.utils.translation -- that module depends on the settings.
gettext_noop = lambda s: s
####################
# CORE #
@ -34,34 +36,34 @@ LANGUAGE_CODE = 'en-us'
# Languages we provide translations for, out of the box. The language name
# should be the utf-8 encoded local name for the language.
LANGUAGES = (
('bn', _('Bengali')),
('cs', _('Czech')),
('cy', _('Welsh')),
('da', _('Danish')),
('de', _('German')),
('el', _('Greek')),
('en', _('English')),
('es', _('Spanish')),
('es_AR', _('Argentinean Spanish')),
('fr', _('French')),
('gl', _('Galician')),
('hu', _('Hungarian')),
('he', _('Hebrew')),
('is', _('Icelandic')),
('it', _('Italian')),
('ja', _('Japanese')),
('nl', _('Dutch')),
('no', _('Norwegian')),
('pt-br', _('Brazilian')),
('ro', _('Romanian')),
('ru', _('Russian')),
('sk', _('Slovak')),
('sl', _('Slovenian')),
('sr', _('Serbian')),
('sv', _('Swedish')),
('uk', _('Ukrainian')),
('zh-cn', _('Simplified Chinese')),
('zh-tw', _('Traditional Chinese')),
('bn', gettext_noop('Bengali')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
('de', gettext_noop('German')),
('el', gettext_noop('Greek')),
('en', gettext_noop('English')),
('es', gettext_noop('Spanish')),
('es_AR', gettext_noop('Argentinean Spanish')),
('fr', gettext_noop('French')),
('gl', gettext_noop('Galician')),
('hu', gettext_noop('Hungarian')),
('he', gettext_noop('Hebrew')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')),
('pt-br', gettext_noop('Brazilian')),
('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')),
('sk', gettext_noop('Slovak')),
('sl', gettext_noop('Slovenian')),
('sr', gettext_noop('Serbian')),
('sv', gettext_noop('Swedish')),
('uk', gettext_noop('Ukrainian')),
('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')),
)
# Languages using BiDi (right-to-left) layout

View File

@ -514,7 +514,7 @@ msgstr "Supprimé %s."
#: contrib/admin/views/main.py:343
msgid "No fields changed."
msgstr "Aucun champs modifié."
msgstr "Aucun champ modifié."
#: contrib/admin/views/main.py:346
#, python-format
@ -1906,7 +1906,7 @@ msgstr ""
#: db/models/fields/__init__.py:40
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "%(optname)s avec le champs %(fieldname)s existe déjà."
msgstr "%(optname)s avec le champ %(fieldname)s existe déjà."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:11+0200\n"
"PO-Revision-Date: 2005-12-20 10:48+0100\n"
"PO-Revision-Date: 2006-07-03 14:06+0200\n"
"Last-Translator: Afonso Fernández Nogueira <fonzzo.django@gmail.com>\n"
"Language-Team: Galego\n"
"MIME-Version: 1.0\n"
@ -91,9 +91,8 @@ msgstr ""
"comentario foi borrado\" no canto do seu contido."
#: contrib/comments/models.py:91
#, fuzzy
msgid "comments"
msgstr "comentario"
msgstr "comentarios"
#: contrib/comments/models.py:131 contrib/comments/models.py:207
msgid "Content object"
@ -120,21 +119,19 @@ msgstr "nome da persoa"
#: contrib/comments/models.py:171
msgid "ip address"
msgstr "Enderezo IP"
msgstr "enderezo IP"
#: contrib/comments/models.py:173
msgid "approved by staff"
msgstr "aprobado polos moderadores"
#: contrib/comments/models.py:176
#, fuzzy
msgid "free comment"
msgstr "Comentario libre"
msgstr "comentario libre"
#: contrib/comments/models.py:177
#, fuzzy
msgid "free comments"
msgstr "Comentarios libres"
msgstr "comentarios libres"
#: contrib/comments/models.py:233
msgid "score"
@ -145,14 +142,12 @@ msgid "score date"
msgstr "data da puntuación"
#: contrib/comments/models.py:237
#, fuzzy
msgid "karma score"
msgstr "Puntuación de karma"
msgstr "puntos de karma"
#: contrib/comments/models.py:238
#, fuzzy
msgid "karma scores"
msgstr "Puntuacións de karma"
msgstr "puntos de karma"
#: contrib/comments/models.py:242
#, python-format
@ -175,14 +170,12 @@ msgid "flag date"
msgstr "data da marca"
#: contrib/comments/models.py:268
#, fuzzy
msgid "user flag"
msgstr "Marca de usuario"
msgstr "marca de usuario"
#: contrib/comments/models.py:269
#, fuzzy
msgid "user flags"
msgstr "Marcas de usuario"
msgstr "marcas de usuario"
#: contrib/comments/models.py:273
#, python-format
@ -194,19 +187,17 @@ msgid "deletion date"
msgstr "data de borrado"
#: contrib/comments/models.py:280
#, fuzzy
msgid "moderator deletion"
msgstr "Borrado de moderación"
msgstr "borrado de moderador"
#: contrib/comments/models.py:281
#, fuzzy
msgid "moderator deletions"
msgstr "Borrados de moderación"
msgstr "borrados de moderador"
#: contrib/comments/models.py:285
#, python-format
msgid "Moderator deletion by %r"
msgstr "Borrado de moderación por %r"
msgstr "Borrado polo moderador %r"
#: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote"
@ -218,7 +209,7 @@ msgstr "ID de comentario non válida"
#: contrib/comments/views/karma.py:25
msgid "No voting for yourself"
msgstr "Non se pode votar a si mesmo"
msgstr "Vostede non se pode votar a si mesmo"
#: contrib/comments/views/comments.py:28
msgid ""
@ -297,9 +288,8 @@ msgid "Password:"
msgstr "Contrasinal:"
#: contrib/comments/templates/comments/form.html:6
#, fuzzy
msgid "Forgotten your password?"
msgstr "Cambiar o contrasinal"
msgstr "Esqueceu o contrasinal?"
#: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3
@ -320,7 +310,7 @@ msgstr "Cambiar o contrasinal"
#: contrib/admin/templates/admin_doc/index.html:4
#: contrib/admin/templates/admin_doc/model_index.html:5
msgid "Log out"
msgstr "Saír"
msgstr "Rematar sesión"
#: contrib/comments/templates/comments/form.html:12
msgid "Ratings"
@ -329,33 +319,30 @@ msgstr ""
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Required"
msgstr ""
msgstr "Requirido"
#: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23
msgid "Optional"
msgstr ""
msgstr "Opcional"
#: contrib/comments/templates/comments/form.html:23
msgid "Post a photo"
msgstr ""
msgstr "Publicar unha foto"
#: contrib/comments/templates/comments/form.html:27
#: contrib/comments/templates/comments/freeform.html:5
#, fuzzy
msgid "Comment:"
msgstr "Comentario"
msgstr "Comentario:"
#: contrib/comments/templates/comments/form.html:32
#: contrib/comments/templates/comments/freeform.html:9
#, fuzzy
msgid "Preview comment"
msgstr "Comentario libre"
msgstr "Previsualizar comentario"
#: contrib/comments/templates/comments/freeform.html:4
#, fuzzy
msgid "Your name:"
msgstr "nome de usuario"
msgstr "Nome:"
#: contrib/admin/filterspecs.py:40
#, python-format
@ -440,12 +427,13 @@ msgstr "Todas as datas"
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
msgstr ""
msgstr "Insira un nome de usuario e un contrasinal correctos. Teña en conta que "
"nos dous campos se distingue entre maiúsculas e minúsculas."
#: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25
msgid "Log in"
msgstr "Entrar"
msgstr "Iniciar sesión"
#: contrib/admin/views/decorators.py:61
msgid ""
@ -757,7 +745,7 @@ msgstr "Sentímolo, pero non se atopou a páxina solicitada."
#: contrib/admin/templates/admin/index.html:17
#, python-format
msgid "Models available in the %(name)s application."
msgstr ""
msgstr "Modelos dispoñíbeis na aplicación %(name)s."
#: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15
@ -1061,12 +1049,11 @@ msgstr "Hora"
#: contrib/admin/templates/widget/file.html:2
msgid "Currently:"
msgstr ""
msgstr "Agora:"
#: contrib/admin/templates/widget/file.html:3
#, fuzzy
msgid "Change:"
msgstr "Modificar"
msgstr "Modificar:"
#: contrib/redirects/models.py:7
msgid "redirect from"
@ -1155,24 +1142,20 @@ msgid "codename"
msgstr "código"
#: contrib/auth/models.py:17
#, fuzzy
msgid "permission"
msgstr "Permiso"
msgstr "permiso"
#: contrib/auth/models.py:18 contrib/auth/models.py:27
#, fuzzy
msgid "permissions"
msgstr "Permisos"
msgstr "permisos"
#: contrib/auth/models.py:29
#, fuzzy
msgid "group"
msgstr "Grupo"
msgstr "grupo"
#: contrib/auth/models.py:30 contrib/auth/models.py:65
#, fuzzy
msgid "groups"
msgstr "Grupos"
msgstr "grupos"
#: contrib/auth/models.py:55
msgid "username"
@ -1231,19 +1214,16 @@ msgstr ""
"permisos concedidos a cada un dos grupos aos que pertence."
#: contrib/auth/models.py:67
#, fuzzy
msgid "user permissions"
msgstr "Permisos"
msgstr "permisos de usuario"
#: contrib/auth/models.py:70
#, fuzzy
msgid "user"
msgstr "Usuario"
msgstr "usuario"
#: contrib/auth/models.py:71
#, fuzzy
msgid "users"
msgstr "Usuarios"
msgstr "usuarios"
#: contrib/auth/models.py:76
msgid "Personal info"
@ -1262,18 +1242,17 @@ msgid "Groups"
msgstr "Grupos"
#: contrib/auth/models.py:219
#, fuzzy
msgid "message"
msgstr "Mensaxe"
msgstr "mensaxe"
#: contrib/auth/forms.py:30
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
msgstr ""
msgstr "Semella que o seu navegador non acepta 'cookies'. Requírense "
"'cookies' para iniciar sesión."
#: contrib/contenttypes/models.py:25
#, fuzzy
msgid "python model class name"
msgstr "nome do módulo Python"
@ -1410,54 +1389,52 @@ msgid "December"
msgstr "decembro"
#: utils/dates.py:19
#, fuzzy
msgid "jan"
msgstr "e"
msgstr "xan"
#: utils/dates.py:19
msgid "feb"
msgstr ""
msgstr "feb"
#: utils/dates.py:19
msgid "mar"
msgstr ""
msgstr "mar"
#: utils/dates.py:19
msgid "apr"
msgstr ""
msgstr "abr"
#: utils/dates.py:19
#, fuzzy
msgid "may"
msgstr "día"
msgstr "mai"
#: utils/dates.py:19
msgid "jun"
msgstr ""
msgstr "xuñ"
#: utils/dates.py:20
msgid "jul"
msgstr ""
msgstr "xul"
#: utils/dates.py:20
msgid "aug"
msgstr ""
msgstr "ago"
#: utils/dates.py:20
msgid "sep"
msgstr ""
msgstr "set"
#: utils/dates.py:20
msgid "oct"
msgstr ""
msgstr "out"
#: utils/dates.py:20
msgid "nov"
msgstr ""
msgstr "nov"
#: utils/dates.py:20
msgid "dec"
msgstr ""
msgstr "dec"
#: utils/dates.py:27
msgid "Jan."
@ -1502,8 +1479,8 @@ msgstr[1] "meses"
#: utils/timesince.py:14
msgid "week"
msgid_plural "weeks"
msgstr[0] ""
msgstr[1] ""
msgstr[0] "semana"
msgstr[1] "semanas"
#: utils/timesince.py:15
msgid "day"
@ -1545,7 +1522,7 @@ msgstr "alemán"
#: conf/global_settings.py:42
msgid "Greek"
msgstr ""
msgstr "grego"
#: conf/global_settings.py:43
msgid "English"
@ -1565,11 +1542,11 @@ msgstr "galego"
#: conf/global_settings.py:47
msgid "Hungarian"
msgstr ""
msgstr "húngaro"
#: conf/global_settings.py:48
msgid "Hebrew"
msgstr ""
msgstr "hebreo"
#: conf/global_settings.py:49
msgid "Icelandic"
@ -1581,11 +1558,11 @@ msgstr "italiano"
#: conf/global_settings.py:51
msgid "Japanese"
msgstr ""
msgstr "xaponés"
#: conf/global_settings.py:52
msgid "Dutch"
msgstr ""
msgstr "holandés"
#: conf/global_settings.py:53
msgid "Norwegian"
@ -1608,9 +1585,8 @@ msgid "Slovak"
msgstr "eslovaco"
#: conf/global_settings.py:58
#, fuzzy
msgid "Slovenian"
msgstr "eslovaco"
msgstr "esloveno"
#: conf/global_settings.py:59
msgid "Serbian"
@ -1621,9 +1597,8 @@ msgid "Swedish"
msgstr "sueco"
#: conf/global_settings.py:61
#, fuzzy
msgid "Ukrainian"
msgstr "brasileiro"
msgstr "ucraíno"
#: conf/global_settings.py:62
msgid "Simplified Chinese"
@ -1631,20 +1606,19 @@ msgstr "chinés simplificado"
#: conf/global_settings.py:63
msgid "Traditional Chinese"
msgstr ""
msgstr "chinés tradicional"
#: core/validators.py:60
msgid "This value must contain only letters, numbers and underscores."
msgstr "Este valor soamente pode conter letras, números e guións baixos (_)."
#: core/validators.py:64
#, fuzzy
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
msgstr ""
"Este valor soamente pode conter letras, números, guións baixos (_) e barras "
"inclinadas."
"Este valor soamente pode conter letras, números, guións baixos (_), guións (-) e barras "
"inclinadas (/)."
#: core/validators.py:72
msgid "Uppercase letters are not allowed here."
@ -1903,9 +1877,9 @@ msgstr ""
"comeza con \"%(start)s\")."
#: db/models/manipulators.py:302
#, fuzzy, python-format
#, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr "Xa existe un/ha %(optname)s con este/a %(fieldname)s."
msgstr "Xa existe un obxecto %(object)s con este %(type)s para o campo %(field)s."
#: db/models/fields/__init__.py:40
#, python-format
@ -1919,19 +1893,16 @@ msgid "This field is required."
msgstr "Requírese este campo."
#: db/models/fields/__init__.py:337
#, fuzzy
msgid "This value must be an integer."
msgstr "Este valor ten que ser unha potencia de %s."
msgstr "Este valor ten que ser un número enteiro."
#: db/models/fields/__init__.py:369
#, fuzzy
msgid "This value must be either True or False."
msgstr "Este valor ten que ser unha potencia de %s."
msgstr "Este valor ten que verdadeiro ou falso."
#: db/models/fields/__init__.py:385
#, fuzzy
msgid "This field cannot be null."
msgstr "Este campo non é válido."
msgstr "Este campo non pode ser nulo."
#: db/models/fields/__init__.py:562
msgid "Enter a valid filename."
@ -1943,12 +1914,10 @@ msgid "Please enter a valid %s."
msgstr "Insira un %s válido/a."
#: db/models/fields/related.py:579
#, fuzzy
msgid "Separate multiple IDs with commas."
msgstr " Separe IDs múltiplas con comas."
msgstr "Separe IDs múltiplas con comas."
#: db/models/fields/related.py:581
#, fuzzy
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2005-12-08 15:28+0100\n"
"PO-Revision-Date: 2005-07-02 13:25+0200\n"
"Last-Translator: Afonso Fernández Nogueira <fonzzo.django@gmail.com>\n"
"Language-Team: Galego\n"
"MIME-Version: 1.0\n"
@ -18,33 +18,32 @@ msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr ""
msgstr "%s dispoñíbeis"
#: contrib/admin/media/js/SelectFilter2.js:41
#, fuzzy
msgid "Choose all"
msgstr "Escolla unha hora"
msgstr "Escoller todo"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr ""
msgstr "Engadir"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr ""
msgstr "Quitar"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr ""
msgstr "%s escollido/a(s)"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr ""
msgstr "Seleccione unha ou varias entrada e faga clic "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr ""
msgstr "Quitar todo"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
@ -52,7 +51,7 @@ msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"xaneiro febeiro marzo abril maio xuño xullo agosto setembro outubro novembro "
"xaneiro febreiro marzo abril maio xuño xullo agosto setembro outubro novembro "
"decembro"
#: contrib/admin/media/js/dateparse.js:27

View File

@ -217,7 +217,7 @@ var DateTimeShortcuts = {
DateTimeShortcuts.dismissCalendar(num);
},
cancelEventPropagation: function(e) {
if (!e) var e = window.event;
if (!e) e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}

View File

@ -19,6 +19,7 @@ function removeEvent(obj, evType, fn) {
return true;
} else if (obj.detachEvent) {
obj.detachEvent("on" + evType, fn);
return true;
} else {
return false;
}

View File

@ -30,7 +30,7 @@
{% endif %}
{% if messages %}
<ul class="messagelist">{% for message in messages %}<li>{{ message }}</li>{% endfor %}</ul>
<ul class="messagelist">{% for message in messages %}<li>{{ message|escape }}</li>{% endfor %}</ul>
{% endif %}
<!-- Content -->

View File

@ -15,7 +15,7 @@
{% for app in app_list %}
<div class="module">
<table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
<caption>{{ app.name }}</caption>
<caption>{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</caption>
{% for model in app.models %}
<tr>
{% if model.perms.change %}

View File

@ -188,7 +188,7 @@ def model_detail(request, app_label, model_name):
'name': field.name,
'data_type': data_type,
'verbose': verbose,
'help': field.help_text,
'help_text': field.help_text,
})
# Gather model methods.

View File

@ -28,9 +28,11 @@
<p><label for="id_comment">{% trans "Comment:" %}</label><br />
<textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p>
<p>
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<p><input type="submit" name="preview" value="{% trans "Preview comment" %}" /></p>
<input type="submit" name="preview" value="{% trans "Preview comment" %}" />
</p>
</form>
{% endif %}

View File

@ -3,9 +3,11 @@
<form action="/comments/postfree/" method="post">
<p><label for="id_person_name">{% trans "Your name:" %}</label> <input type="text" id="id_person_name" name="person_name" /></p>
<p><label for="id_comment">{% trans "Comment:" %}</label><br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p>
<p>
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<p><input type="submit" name="preview" value="{% trans "Preview comment" %}" /></p>
<input type="submit" name="preview" value="{% trans "Preview comment" %}" />
</p>
</form>
{% endif %}

View File

@ -1006,6 +1006,8 @@ def get_validation_errors(outfile, app=None):
# Check core=True, if needed.
for related in opts.get_followed_related_objects():
if not related.edit_inline:
continue
try:
for f in related.opts.fields:
if f.core:
@ -1045,7 +1047,10 @@ def _check_for_validation_errors(app=None):
s = StringIO()
num_errors = get_validation_errors(s, app)
if num_errors:
sys.stderr.write(style.ERROR("Error: %s couldn't be installed, because there were errors in your model:\n" % app))
if app:
sys.stderr.write(style.ERROR("Error: %s couldn't be installed, because there were errors in your model:\n" % app))
else:
sys.stderr.write(style.ERROR("Error: Couldn't install apps, because there were errors in one or more models:\n"))
s.seek(0)
sys.stderr.write(s.read())
sys.exit(1)

View File

@ -2,13 +2,14 @@ from django.conf import settings
import os
def runshell():
args = ['']
args += ["-U%s" % settings.DATABASE_USER]
args = ['psql']
if settings.DATABASE_USER:
args += ["-U", settings.DATABASE_USER]
if settings.DATABASE_PASSWORD:
args += ["-W"]
if settings.DATABASE_HOST:
args += ["-h %s" % settings.DATABASE_HOST]
args.extend(["-h", settings.DATABASE_HOST])
if settings.DATABASE_PORT:
args += ["-p %s" % settings.DATABASE_PORT]
args.extend(["-p", str(settings.DATABASE_PORT)])
args += [settings.DATABASE_NAME]
os.execvp('psql', args)

View File

@ -2,18 +2,56 @@ from django.db import transaction
from django.db.backends.sqlite3.base import quote_name
def get_table_list(cursor):
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
"Returns a list of table names in the current database."
# Skip the sqlite_sequence system table used for autoincrement key
# generation.
cursor.execute("""
SELECT name FROM sqlite_master
WHERE type='table' AND NOT name='sqlite_sequence'
ORDER BY name""")
return [row[0] for row in cursor.fetchall()]
def get_table_description(cursor, table_name):
cursor.execute("PRAGMA table_info(%s)" % quote_name(table_name))
return [(row[1], row[2], None, None) for row in cursor.fetchall()]
"Returns a description of the table, with the DB-API cursor.description interface."
return [(info['name'], info['type'], None, None, None, None,
info['null_ok']) for info in _table_info(cursor, table_name)]
def get_relations(cursor, table_name):
raise NotImplementedError
def get_indexes(cursor, table_name):
raise NotImplementedError
"""
Returns a dictionary of fieldname -> infodict for the given table,
where each infodict is in the format:
{'primary_key': boolean representing whether it's the primary key,
'unique': boolean representing whether it's a unique index}
"""
indexes = {}
for info in _table_info(cursor, table_name):
indexes[info['name']] = {'primary_key': info['pk'] != 0,
'unique': False}
cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name))
# seq, name, unique
for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:
if not unique:
continue
cursor.execute('PRAGMA index_info(%s)' % quote_name(index))
info = cursor.fetchall()
# Skip indexes across multiple fields
if len(info) != 1:
continue
name = info[0][2] # seqno, cid, name
indexes[name]['unique'] = True
return indexes
def _table_info(cursor, name):
cursor.execute('PRAGMA table_info(%s)' % quote_name(name))
# cid, name, type, notnull, dflt_value, pk
return [{'name': field[1],
'type': field[2],
'null_ok': not field[3],
'pk': field[5] # undocumented
} for field in cursor.fetchall()]
# Maps SQL types to Django Field types. Some of the SQL types have multiple
# entries here because SQLite allows for anything and doesn't normalize the

View File

@ -44,6 +44,11 @@ class ModelBase(type):
# For 'django.contrib.sites.models', this would be 'sites'.
new_class._meta.app_label = model_module.__name__.split('.')[-2]
# Bail out early if we have already created this class.
m = get_model(new_class._meta.app_label, name)
if m is not None:
return m
# Add all attributes to the class.
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj)
@ -60,10 +65,10 @@ class ModelBase(type):
new_class._prepare()
register_models(new_class._meta.app_label, new_class)
# Because of the way imports happen (recursively), we may or may not be
# the first class for this model to register with the framework. There
# should only be one class for each model, so we must always return the
# registered version.
# Because of the way imports happen (recursively), we may or may not be
# the first class for this model to register with the framework. There
# should only be one class for each model, so we must always return the
# registered version.
return get_model(new_class._meta.app_label, name)
class Model(object):

View File

@ -679,7 +679,7 @@ def get_cached_row(klass, row, index_start):
def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen):
"""
Helper function that recursively populates the select, tables and where (in
place) for fill-cache queries.
place) for select_related queries.
"""
backend = opts.connection_info.backend
for f in opts.fields:
@ -701,6 +701,7 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen)
def parse_lookup(kwarg_items, opts):
# Helper function that handles converting API kwargs
# (e.g. "name__exact": "tom") to SQL.
# Returns a tuple of (tables, joins, where, params).
# 'joins' is a sorted dictionary describing the tables that must be joined
# to complete the query. The dictionary is sorted because creation order

View File

@ -773,15 +773,18 @@ class DatetimeField(TextField):
def html2python(data):
"Converts the field into a datetime.datetime object"
import datetime
date, time = data.split()
y, m, d = date.split('-')
timebits = time.split(':')
h, mn = timebits[:2]
if len(timebits) > 2:
s = int(timebits[2])
else:
s = 0
return datetime.datetime(int(y), int(m), int(d), int(h), int(mn), s)
try:
date, time = data.split()
y, m, d = date.split('-')
timebits = time.split(':')
h, mn = timebits[:2]
if len(timebits) > 2:
s = int(timebits[2])
else:
s = 0
return datetime.datetime(int(y), int(m), int(d), int(h), int(mn), s)
except ValueError:
return None
html2python = staticmethod(html2python)
class DateField(TextField):
@ -806,7 +809,7 @@ class DateField(TextField):
time_tuple = time.strptime(data, '%Y-%m-%d')
return datetime.date(*time_tuple[0:3])
except (ValueError, TypeError):
return data
return None
html2python = staticmethod(html2python)
class TimeField(TextField):

View File

@ -318,7 +318,7 @@ class Parser(object):
self.tags.update(lib.tags)
self.filters.update(lib.filters)
def compile_filter(self,token):
def compile_filter(self, token):
"Convenient wrapper for FilterExpression"
return FilterExpression(token, self)
@ -543,11 +543,14 @@ class FilterExpression(object):
raise TemplateSyntaxError, "Could not parse the remainder: %s" % token[upto:]
self.var, self.filters = var, filters
def resolve(self, context):
def resolve(self, context, ignore_failures=False):
try:
obj = resolve_variable(self.var, context)
except VariableDoesNotExist:
obj = settings.TEMPLATE_STRING_IF_INVALID
if ignore_failures:
return None
else:
return settings.TEMPLATE_STRING_IF_INVALID
for func, args in self.filters:
arg_vals = []
for lookup, arg in args:
@ -611,7 +614,11 @@ def resolve_variable(path, context):
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
"""
if path[0].isdigit():
if path == 'False':
current = False
elif path == 'True':
current = True
elif path[0].isdigit():
number_type = '.' in path and float or int
try:
current = number_type(path)

View File

@ -37,7 +37,7 @@ class Context(object):
for d in self.dicts:
if d.has_key(key):
return d[key]
return settings.TEMPLATE_STRING_IF_INVALID
raise KeyError(key)
def __delitem__(self, key):
"Delete a variable from the current context"
@ -49,7 +49,7 @@ class Context(object):
return True
return False
def get(self, key, otherwise):
def get(self, key, otherwise=None):
for d in self.dicts:
if d.has_key(key):
return d[key]

View File

@ -430,20 +430,32 @@ def filesizeformat(bytes):
return "%.1f MB" % (bytes / (1024 * 1024))
return "%.1f GB" % (bytes / (1024 * 1024 * 1024))
def pluralize(value):
"Returns 's' if the value is not 1, for '1 vote' vs. '2 votes'"
def pluralize(value, arg='s'):
"""
Returns a plural suffix if the value is not 1, for '1 vote' vs. '2 votes'
By default, 's' is used as a suffix; if an argument is provided, that string
is used instead. If the provided argument contains a comma, the text before
the comma is used for the singular case.
"""
if not ',' in arg:
arg = ',' + arg
bits = arg.split(',')
if len(bits) > 2:
return ''
singular_suffix, plural_suffix = bits[:2]
try:
if int(value) != 1:
return 's'
return plural_suffix
except ValueError: # invalid string that's not a number
pass
except TypeError: # value isn't a string or a number; maybe it's a list?
try:
if len(value) != 1:
return 's'
return plural_suffix
except TypeError: # len() of unsized object
pass
return ''
return singular_suffix
def phone2numeric(value):
"Takes a phone number and converts it in to its numerical equivalent"

View File

@ -45,7 +45,10 @@ class FirstOfNode(Node):
def render(self, context):
for var in self.vars:
value = resolve_variable(var, context)
try:
value = resolve_variable(var, context)
except VariableDoesNotExist:
continue
if value:
return str(value)
return ''
@ -144,8 +147,14 @@ class IfEqualNode(Node):
return "<IfEqualNode>"
def render(self, context):
val1 = resolve_variable(self.var1, context)
val2 = resolve_variable(self.var2, context)
try:
val1 = resolve_variable(self.var1, context)
except VariableDoesNotExist:
val1 = None
try:
val2 = resolve_variable(self.var2, context)
except VariableDoesNotExist:
val2 = None
if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
return self.nodelist_true.render(context)
return self.nodelist_false.render(context)
@ -177,7 +186,7 @@ class IfNode(Node):
if self.link_type == IfNode.LinkTypes.or_:
for ifnot, bool_expr in self.bool_exprs:
try:
value = bool_expr.resolve(context)
value = bool_expr.resolve(context, True)
except VariableDoesNotExist:
value = None
if (value and not ifnot) or (ifnot and not value):
@ -186,7 +195,7 @@ class IfNode(Node):
else:
for ifnot, bool_expr in self.bool_exprs:
try:
value = bool_expr.resolve(context)
value = bool_expr.resolve(context, True)
except VariableDoesNotExist:
value = None
if not ((value and not ifnot) or (ifnot and not value)):

View File

@ -12,7 +12,7 @@ class GetAvailableLanguagesNode(Node):
def render(self, context):
from django.conf import settings
context[self.variable] = settings.LANGUAGES
context[self.variable] = [(k, translation.gettext(v)) for k, v in settings.LANGUAGES]
return ''
class GetCurrentLanguageNode(Node):
@ -30,7 +30,7 @@ class GetCurrentLanguageBidiNode(Node):
def render(self, context):
context[self.variable] = translation.get_language_bidi()
return ''
class TranslateNode(Node):
def __init__(self, value, noop):
self.value = value
@ -171,7 +171,7 @@ def do_translate(parser, token):
else:
noop = False
return (value, noop)
(value, noop) = TranslateParser(token.contents).top()
value, noop = TranslateParser(token.contents).top()
return TranslateNode(value, noop)
def do_block_translate(parser, token):
@ -216,7 +216,7 @@ def do_block_translate(parser, token):
raise TemplateSyntaxError, "unknown subtag %s for 'blocktrans' found" % tag
return (countervar, counter, extra_context)
(countervar, counter, extra_context) = BlockTranslateParser(token.contents).top()
countervar, counter, extra_context = BlockTranslateParser(token.contents).top()
singular = []
plural = []

View File

@ -6,7 +6,10 @@ Synchronization primitives:
(Contributed to Django by eugene@lazutkin.com)
"""
import threading
try:
import threading
except ImportError:
import dummy_threading as threading
class RWLock:
"""

View File

@ -0,0 +1,8 @@
from django.conf import settings
if settings.USE_I18N:
from trans_real import *
else:
from trans_null import *
del settings

View File

@ -0,0 +1,18 @@
# These are versions of the functions in django.utils.translation.trans_real
# that don't actually do anything. This is purely for performance, so that
# settings.USE_I18N = False can use this module rather than trans_real.py.
from django.conf import settings
def ngettext(singular, plural, number):
if number == 1: return singular
return plural
ngettext_lazy = ngettext
gettext = gettext_noop = gettext_lazy = _ = lambda x: x
string_concat = lambda *strings: ''.join([str(el) for el in strings])
activate = lambda x: None
deactivate = install = lambda: None
get_language = lambda: settings.LANGUAGE_CODE
get_date_formats = lambda: settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT
get_partial_date_formats = lambda: settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT

View File

@ -1,4 +1,4 @@
"translation helper functions"
"Translation helper functions"
import os, re, sys
import gettext as gettext_module
@ -221,7 +221,6 @@ def get_language_bidi():
False = left-to-right layout
True = right-to-left layout
"""
from django.conf import settings
return get_language() in settings.LANGUAGES_BIDI
@ -389,7 +388,7 @@ def get_partial_date_formats():
def install():
"""
Installs the gettext function as the default translation function under
the name _.
the name '_'.
"""
__builtins__['_'] = gettext

View File

@ -1121,35 +1121,37 @@ Note this is only available in MySQL and requires direct manipulation of the
database to add the full-text index.
Default lookups are exact
~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------
If you don't provide a lookup type -- that is, if your keyword argument doesn't
contain a double underscore -- the lookup type is assumed to be ``exact``.
For example, the following two statements are equivalent::
Blog.objects.get(id=14)
Blog.objects.get(id__exact=14)
Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id=14) # __exact is implied
This is for convenience, because ``exact`` lookups are the common case.
The pk lookup shortcut
~~~~~~~~~~~~~~~~~~~~~~
----------------------
For convenience, Django provides a ``pk`` lookup type, which stands for
"primary_key". This is shorthand for "an exact lookup on the primary-key."
In the example ``Blog`` model, the primary key is the ``id`` field, so these
two statements are equivalent::
three statements are equivalent::
Blog.objects.get(id__exact=14)
Blog.objects.get(pk=14)
Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact
``pk`` lookups also work across joins. For example, these two statements are
``pk`` lookups also work across joins. For example, these three statements are
equivalent::
Entry.objects.filter(blog__id__exact=3)
Entry.objects.filter(blog__pk=3)
Entry.objects.filter(blog__id__exact=3) # Explicit form
Entry.objects.filter(blog__id=3) # __exact is implied
Entry.objects.filter(blog__pk=3) # __pk implies __id__exact
Lookups that span relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1550,6 +1552,21 @@ loaded, Django iterates over every model in ``INSTALLED_APPS`` and creates the
backward relationships in memory as needed. Essentially, one of the functions
of ``INSTALLED_APPS`` is to tell Django the entire model domain.
Queries over related objects
----------------------------
Queries involving related objects follow the same rules as queries involving
normal value fields. When specifying the the value for a query to match, you
may use either an object instance itself, or the primary key value for the
object.
For example, if you have a Blog object ``b`` with ``id=5``, the following
three queries would be identical::
Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly
Deleting objects
================

View File

@ -126,8 +126,9 @@ you run it, you'll want to look over the generated models yourself to make
customizations. In particular, you'll need to rearrange models' order, so that
models that refer to other models are ordered properly.
Primary keys are automatically introspected for PostgreSQL and MySQL, in which
case Django puts in the ``primary_key=True`` where needed.
Primary keys are automatically introspected for PostgreSQL, MySQL and
SQLite, in which case Django puts in the ``primary_key=True`` where
needed.
``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
only works in PostgreSQL and with certain types of MySQL tables.

View File

@ -50,7 +50,7 @@ model that "knows" how to create or modify instances of that model and how to
validate data for the object. Manipulators come in two flavors:
``AddManipulators`` and ``ChangeManipulators``. Functionally they are quite
similar, but the former knows how to create new instances of the model, while
the later modifies existing instances. Both types of classes are automatically
the latter modifies existing instances. Both types of classes are automatically
created when you define a new class::
>>> from mysite.myapp.models import Place

View File

@ -110,7 +110,7 @@ efficient. Here's the above "Hello World" example rewritten to use
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.utils.httpwrappers import HttpResponse
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.

View File

@ -10,18 +10,22 @@ Cookies contain a session ID -- not the data itself.
Enabling sessions
=================
Sessions are implemented via middleware_.
Sessions are implemented via a piece of middleware_ and a Django model.
Turn session functionality on and off by editing the ``MIDDLEWARE_CLASSES``
setting. To activate sessions, make sure ``MIDDLEWARE_CLASSES`` contains
``'django.contrib.sessions.middleware.SessionMiddleware'``.
To enable session functionality, do these two things:
The default ``settings.py`` created by ``django-admin.py startproject`` has
``SessionMiddleware`` activated.
* Edit the ``MIDDLEWARE_CLASSES`` setting and make sure
``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``.
The default ``settings.py`` created by ``django-admin.py startproject`` has
``SessionMiddleware`` activated.
* Add ``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting, and
run ``manage.py syncdb`` to install the single database table that stores
session data.
If you don't want to use sessions, you might as well remove the
``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES``. It'll save you a small
bit of overhead.
``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'``
from your ``INSTALLED_APPS``. It'll save you a small bit of overhead.
.. _middleware: http://www.djangoproject.com/documentation/middleware/

View File

@ -729,6 +729,10 @@ TIME_ZONE
Default: ``'America/Chicago'``
A string representing the time zone for this installation. `See available choices`_.
(Note that list of available choices lists more than one on the same line;
you'll want to use just one of the choices for a given time zone. For instance,
one line says ``'Europe/London GB GB-Eire'``, but you should use the first bit
of that -- ``'Europe/London'`` -- as your ``TIME_ZONE`` setting.)
Note that this is the time zone to which Django will convert all dates/times --
not necessarily the timezone of the server. For example, one server may serve
@ -750,7 +754,7 @@ Default: ``True``
A boolean that specifies whether Django's internationalization system should be
enabled. This provides an easy way to turn it off, for performance. If this is
set to ``False, Django will make some optimizations so as not to load the
set to ``False``, Django will make some optimizations so as not to load the
internationalization machinery.
YEAR_MONTH_FORMAT

View File

@ -951,12 +951,26 @@ any string.
pluralize
~~~~~~~~~
Returns ``'s'`` if the value is not 1.
Returns a plural suffix if the value is not 1. By default, this suffix is ``'s'``.
Example::
You have {{ num_messages }} message{{ num_messages|pluralize }}.
For words that require a suffix other than ``'s'``, you can provide an alternate
suffix as a parameter to the filter.
Example::
You have {{ num_walruses }} walrus{{ num_walrus|pluralize:"es" }}.
For words that don't pluralize by simple suffix, you can specify both a
singular and plural suffix, separated by a comma.
Example::
You have {{ num_cherries }} cherr{{ num_cherries|pluralize:"y,ies" }}.
pprint
~~~~~~

View File

@ -313,6 +313,36 @@ False
>>> pluralize(2)
's'
>>> pluralize([1])
''
>>> pluralize([])
's'
>>> pluralize([1,2,3])
's'
>>> pluralize(1,'es')
''
>>> pluralize(0,'es')
'es'
>>> pluralize(2,'es')
'es'
>>> pluralize(1,'y,ies')
'y'
>>> pluralize(0,'y,ies')
'ies'
>>> pluralize(2,'y,ies')
'ies'
>>> pluralize(0,'y,ies,error')
''
>>> phone2numeric('0800 flowers')
'0800 3569377'

View File

@ -78,7 +78,7 @@ TEMPLATE_TESTS = {
'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
# Fail silently when a variable is not found in the current context
'basic-syntax04': ("as{{ missing }}df", {}, "asdf"),
'basic-syntax04': ("as{{ missing }}df", {}, "asINVALIDdf"),
# A variable may not contain more than one word
'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
@ -94,7 +94,7 @@ TEMPLATE_TESTS = {
'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
# Fail silently when a variable's attribute isn't found
'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, ""),
'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, "INVALID"),
# Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
@ -110,10 +110,10 @@ TEMPLATE_TESTS = {
'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
# Fail silently when a variable's dictionary key isn't found
'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, ""),
'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, "INVALID"),
# Fail silently when accessing a non-simple method
'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ""),
'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, "INVALID"),
# Basic filter usage
'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
@ -152,7 +152,7 @@ TEMPLATE_TESTS = {
'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
# Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "12"),
'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "1INVALID2"),
# In methods that raise an exception without a "silent_variable_attribute" set to True,
# the exception propogates
@ -495,7 +495,7 @@ TEMPLATE_TESTS = {
'{{ item.foo }}' + \
'{% endfor %},' + \
'{% endfor %}',
{}, ''),
{}, 'INVALID:INVALIDINVALIDINVALIDINVALIDINVALIDINVALIDINVALID,'),
### TEMPLATETAG TAG #######################################################
'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
@ -579,6 +579,9 @@ def run_tests(verbosity=0, standalone=False):
# Turn TEMPLATE_DEBUG off, because tests assume that.
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
# Set TEMPLATE_STRING_IF_INVALID to a known string
old_invalid, settings.TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID, 'INVALID'
for name, vals in tests:
install()
if 'LANGUAGE_CODE' in vals[1]:
@ -609,6 +612,7 @@ def run_tests(verbosity=0, standalone=False):
loader.template_source_loaders = old_template_loaders
deactivate()
settings.TEMPLATE_DEBUG = old_td
settings.TEMPLATE_STRING_IF_INVALID = old_invalid
if failed_tests and not standalone:
msg = "Template tests %s failed." % failed_tests

View File

@ -0,0 +1,13 @@
from django.db import models
class First(models.Model):
second = models.IntegerField()
class Second(models.Model):
first = models.ForeignKey(First, related_name = 'the_first')
# If ticket #1578 ever slips back in, these models will not be able to be
# created (the field names being lower-cased versions of their opposite
# classes is important here).
API_TESTS = ""