mirror of
https://github.com/django/django.git
synced 2025-07-05 10:19:20 +00:00
Merged to [3519]
git-svn-id: http://code.djangoproject.com/svn/django/branches/generic-auth@4024 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
bf629e5a4d
commit
dc59c670b8
20
AUTHORS
20
AUTHORS
@ -16,12 +16,23 @@ before Simon departed and currently oversees things with Adrian.
|
||||
|
||||
Wilson Miner <http://www.wilsonminer.com/>, who designed Django's admin
|
||||
interface, pretty error pages, official Web site (djangoproject.com) and has
|
||||
made many other contributions.
|
||||
made many other contributions. He makes us look good.
|
||||
|
||||
Malcolm Tredinnick <http://www.pointy-stick.com/blog/>, who has made
|
||||
significant contributions to all levels of the framework, from its database
|
||||
layer to template system and documentation.
|
||||
|
||||
Georg "Hugo" Bauer <http://hugo.muensterland.org/>, who added
|
||||
internationalization support, manages i18n contributions and has made a ton
|
||||
of excellent tweaks, feature additions and bug fixes.
|
||||
|
||||
Luke Plant <http://lukeplant.me.uk/>, who has contributed many excellent
|
||||
improvements, including database-level improvements, the CSRF middleware and
|
||||
unit tests.
|
||||
|
||||
Russell Keith-Magee <freakboy@iinet.net.au>, who has contributed many excellent
|
||||
improvements, including refactoring of the Django ORM code and unit tests.
|
||||
|
||||
Robert Wittams <http://robert.wittams.com/>, who majorly refactored the Django
|
||||
admin application to allow for easier reuse and has made a ton of excellent
|
||||
tweaks, feature additions and bug fixes.
|
||||
@ -54,10 +65,13 @@ 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
|
||||
Baishampayan Ghose
|
||||
martin.glueck@gmail.com
|
||||
Simon Greenhill <dev@simon.net.nz>
|
||||
Espen Grindhaug <http://grindhaug.org/>
|
||||
Brant Harris
|
||||
hipertracker@gmail.com
|
||||
@ -69,8 +83,8 @@ answer newbie questions, and generally made Django that much better:
|
||||
Michael Josephson <http://www.sdjournal.com/>
|
||||
jpellerin@gmail.com
|
||||
junzhang.jn@gmail.com
|
||||
Russell Keith-Magee <freakboy@iinet.net.au>
|
||||
Garth Kidd <http://www.deadlybloodyserious.com/>
|
||||
kilian <kilian.cavalotti@lip6.fr>
|
||||
Sune Kirkeby <http://ibofobi.dk/>
|
||||
Cameron Knight (ckknight)
|
||||
Bruce Kroeze <http://coderseye.com/>
|
||||
@ -96,6 +110,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Sam Newman <http://www.magpiebrain.com/>
|
||||
Neal Norwitz <nnorwitz@google.com>
|
||||
oggie rob <oz.robharvey@gmail.com>
|
||||
Jay Parlar <parlar@gmail.com>
|
||||
pgross@thoughtworks.com
|
||||
phaedo <http://phaedo.cx/>
|
||||
phil@produxion.net
|
||||
@ -116,7 +131,6 @@ answer newbie questions, and generally made Django that much better:
|
||||
Tom Tobin
|
||||
Tom Insam
|
||||
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
||||
Malcolm Tredinnick
|
||||
Amit Upadhyay
|
||||
Geert Vanderkelen
|
||||
Milton Waddams
|
||||
|
19
INSTALL
19
INSTALL
@ -1,7 +1,22 @@
|
||||
Thanks for downloading Django.
|
||||
|
||||
To install it, make sure you have Python 2.3 or greater installed. Then run this command:
|
||||
To install it, make sure you have Python 2.3 or greater installed. Then run
|
||||
this command from the command prompt:
|
||||
|
||||
python setup.py install
|
||||
python setup.py install
|
||||
|
||||
Note this requires a working Internet connection if you don't already have the
|
||||
Python utility "setuptools" installed.
|
||||
|
||||
AS AN ALTERNATIVE, you can just copy the entire "django" directory to Python's
|
||||
site-packages directory, which is located wherever your Python installation
|
||||
lives. Some places you might check are:
|
||||
|
||||
/usr/lib/python2.4/site-packages (Unix, Python 2.4)
|
||||
/usr/lib/python2.3/site-packages (Unix, Python 2.3)
|
||||
C:\\PYTHON\site-packages (Windows)
|
||||
|
||||
This second solution does not require a working Internet connection; it
|
||||
bypasses "setuptools" entirely.
|
||||
|
||||
For more detailed instructions, see docs/install.txt.
|
||||
|
@ -1 +1 @@
|
||||
VERSION = (0, 95, 'post-magic-removal')
|
||||
VERSION = (0, 96, 'pre')
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
def compile_messages():
|
||||
basedir = None
|
||||
|
@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Need to ensure that the i18n framework is enabled
|
||||
from django.conf import settings
|
||||
settings.configure(USE_I18N = True)
|
||||
|
||||
from django.utils.translation import templatize
|
||||
import re
|
||||
import os
|
||||
|
@ -7,7 +7,6 @@ a list of all possible variables.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from django.conf import global_settings
|
||||
|
||||
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
||||
@ -116,7 +115,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 +134,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
|
||||
|
@ -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,38 +36,44 @@ 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')),
|
||||
('ar', gettext_noop('Arabic')),
|
||||
('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')),
|
||||
('ta', gettext_noop('Tamil')),
|
||||
('uk', gettext_noop('Ukrainian')),
|
||||
('zh-cn', gettext_noop('Simplified Chinese')),
|
||||
('zh-tw', gettext_noop('Traditional Chinese')),
|
||||
)
|
||||
|
||||
# Languages using BiDi (right-to-left) layout
|
||||
LANGUAGES_BIDI = ("he",)
|
||||
LANGUAGES_BIDI = ("he", "ar")
|
||||
|
||||
# If you set this to False, Django will make some optimizations so as not
|
||||
# to load the internationalization machinery.
|
||||
USE_I18N = True
|
||||
|
||||
# Not-necessarily-technical managers of the site. They get broken link
|
||||
# notifications and other various e-mails.
|
||||
@ -281,3 +289,9 @@ COMMENTS_FIRST_FEW = 0
|
||||
# A tuple of IP addresses that have been banned from participating in various
|
||||
# Django-powered features.
|
||||
BANNED_IPS = ()
|
||||
|
||||
##################
|
||||
# AUTHENTICATION #
|
||||
##################
|
||||
|
||||
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
|
||||
|
BIN
django/conf/locale/ar/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/ar/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
1989
django/conf/locale/ar/LC_MESSAGES/django.po
Normal file
1989
django/conf/locale/ar/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ar/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ar/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
110
django/conf/locale/ar/LC_MESSAGES/djangojs.po
Normal file
110
django/conf/locale/ar/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,110 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Django SVN\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
|
||||
"PO-Revision-Date: 2006-07-06 23:50+0300\n"
|
||||
"Last-Translator: Ahmad Alhashemi <ahmad@ahmadh.com>\n"
|
||||
"Language-Team: Ahmad Alhashemi <trans@ahmadh.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-Language: Arabic\n"
|
||||
"X-Poedit-Country: Kuwait\n"
|
||||
"X-Poedit-SourceCharset: utf-8\n"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||
#, perl-format
|
||||
msgid "Available %s"
|
||||
msgstr "%s متوفرة"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||
msgid "Choose all"
|
||||
msgstr "اختيار الكل"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||
msgid "Add"
|
||||
msgstr "إضافة"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||
msgid "Remove"
|
||||
msgstr "حذف"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||
#, perl-format
|
||||
msgid "Chosen %s"
|
||||
msgstr "%s اختيرت"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||
msgid "Select your choice(s) and click "
|
||||
msgstr "حدد خيارك أو خياراتك واضغط"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||
msgid "Clear all"
|
||||
msgstr "مسح الكل"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:26
|
||||
#: contrib/admin/media/js/calendar.js:24
|
||||
msgid "January February March April May June July August September October November December"
|
||||
msgstr "يناير فبراير مارس إبريل مايو يونيو يوليو أغسطس سبتمبر أكتوبر نوفمبر ديسمبر"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:27
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||
msgstr "الأحد الأثنين الثلاثاء الأربعاء الخميس الجمعة السبت"
|
||||
|
||||
#: contrib/admin/media/js/calendar.js:25
|
||||
msgid "S M T W T F S"
|
||||
msgstr "أ أ ث أ خ ج س"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||
msgid "Now"
|
||||
msgstr "الآن"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||
msgid "Clock"
|
||||
msgstr "الساعة"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||
msgid "Choose a time"
|
||||
msgstr "اختر وقتا ما"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||
msgid "Midnight"
|
||||
msgstr "منتصف الليل"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||
msgid "6 a.m."
|
||||
msgstr "6 ص."
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||
msgid "Noon"
|
||||
msgstr "الظهر"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||
msgid "Cancel"
|
||||
msgstr "الغاء"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||
msgid "Today"
|
||||
msgstr "اليوم"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||
msgid "Calendar"
|
||||
msgstr "التقويم"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||
msgid "Yesterday"
|
||||
msgstr "يوم أمس"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||
msgid "Tomorrow"
|
||||
msgstr "الغد"
|
||||
|
Binary file not shown.
@ -8,10 +8,10 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-05-16 09:26-0300\n"
|
||||
"POT-Creation-Date: 2006-06-19 11:19-0300\n"
|
||||
"PO-Revision-Date: 2006-05-16 10:05-0300\n"
|
||||
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
|
||||
"Language-Team: Spanish <en@li.org>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=ISO-8859-1\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@ -29,6 +29,10 @@ msgstr "tipo de contenido"
|
||||
msgid "content types"
|
||||
msgstr "tipos de contenido"
|
||||
|
||||
#: contrib/auth/views.py:39
|
||||
msgid "Logged out"
|
||||
msgstr "Sesión cerrada"
|
||||
|
||||
#: contrib/auth/models.py:13 contrib/auth/models.py:26
|
||||
msgid "name"
|
||||
msgstr "nombre"
|
||||
@ -63,7 +67,7 @@ msgstr "nombre"
|
||||
|
||||
#: contrib/auth/models.py:57
|
||||
msgid "last name"
|
||||
msgstr "apellido(s)"
|
||||
msgstr "apellido"
|
||||
|
||||
#: contrib/auth/models.py:58
|
||||
msgid "e-mail address"
|
||||
@ -83,7 +87,7 @@ msgstr "es staff"
|
||||
|
||||
#: contrib/auth/models.py:60
|
||||
msgid "Designates whether the user can log into this admin site."
|
||||
msgstr "Indica si el usuario puede entrar en este sitio de administración."
|
||||
msgstr "Indica si el usuario puede ingresar a este sitio de administración."
|
||||
|
||||
#: contrib/auth/models.py:61
|
||||
msgid "active"
|
||||
@ -149,7 +153,7 @@ msgstr ""
|
||||
"Su navegador Web aparenta no tener cookies activas. Las cookies son un "
|
||||
"requerimiento para poder ingresar."
|
||||
|
||||
#: contrib/auth/forms.py:36 contrib/auth/forms.py:41
|
||||
#: contrib/auth/forms.py:36 contrib/auth/forms.py:43
|
||||
#: contrib/admin/views/decorators.py:9
|
||||
msgid ""
|
||||
"Please enter a correct username and password. Note that both fields are case-"
|
||||
@ -158,6 +162,10 @@ msgstr ""
|
||||
"Por favor ingrese un nombre de usuario y una contraseña correctos. Note que "
|
||||
"ambos campos son sensibles a mayúsculas/minúsculas."
|
||||
|
||||
#: contrib/auth/forms.py:45
|
||||
msgid "This account is inactive."
|
||||
msgstr "Esta cuenta está inactiva"
|
||||
|
||||
#: contrib/redirects/models.py:7
|
||||
msgid "redirect from"
|
||||
msgstr "redirigir desde"
|
||||
@ -182,11 +190,11 @@ msgstr ""
|
||||
"Esto puede ser bien una ruta absoluta (como antes) o una URL completa que "
|
||||
"empiece con 'http://'."
|
||||
|
||||
#: contrib/redirects/models.py:12
|
||||
#: contrib/redirects/models.py:13
|
||||
msgid "redirect"
|
||||
msgstr "redirección"
|
||||
|
||||
#: contrib/redirects/models.py:13
|
||||
#: contrib/redirects/models.py:14
|
||||
msgid "redirects"
|
||||
msgstr "redirecciones"
|
||||
|
||||
@ -247,7 +255,7 @@ msgstr "fecha/hora de env
|
||||
msgid "is public"
|
||||
msgstr "es público"
|
||||
|
||||
#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
|
||||
#: contrib/comments/models.py:85 contrib/admin/views/doc.py:292
|
||||
msgid "IP address"
|
||||
msgstr "Dirección IP"
|
||||
|
||||
@ -413,17 +421,20 @@ msgstr[1] ""
|
||||
"%(text)s"
|
||||
|
||||
#: contrib/comments/views/comments.py:117
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
msgid ""
|
||||
"This comment was posted by a sketchy user:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgstr ""
|
||||
"Este comentario ha sido enviado por un usuario 'sketcky':\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
|
||||
#: contrib/comments/views/comments.py:189
|
||||
#: contrib/comments/views/comments.py:280
|
||||
msgid "Only POSTs are allowed"
|
||||
msgstr "Sólo se admite POST"
|
||||
msgstr "Sólo se admiten POSTs"
|
||||
|
||||
#: contrib/comments/views/comments.py:193
|
||||
#: contrib/comments/views/comments.py:284
|
||||
@ -484,7 +495,7 @@ msgstr "Olvid
|
||||
#: contrib/admin/templates/admin/object_history.html:3
|
||||
#: contrib/admin/templates/admin/change_list.html:5
|
||||
#: contrib/admin/templates/admin/change_form.html:10
|
||||
#: contrib/admin/templates/admin/base.html:23
|
||||
#: contrib/admin/templates/admin/base.html:24
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:3
|
||||
#: contrib/admin/templates/registration/password_change_done.html:3
|
||||
#: contrib/admin/templates/registration/password_change_form.html:3
|
||||
@ -499,7 +510,7 @@ msgstr "Olvid
|
||||
#: contrib/admin/templates/admin_doc/index.html:4
|
||||
#: contrib/admin/templates/admin_doc/model_index.html:5
|
||||
msgid "Log out"
|
||||
msgstr "Terminar sesión"
|
||||
msgstr "Cerrar sesión"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
msgid "Ratings"
|
||||
@ -519,7 +530,7 @@ msgstr "Opcional"
|
||||
msgid "Post a photo"
|
||||
msgstr "Enviar una foto"
|
||||
|
||||
#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:300
|
||||
#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:303
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
@ -596,7 +607,7 @@ msgstr "nombre de dominio"
|
||||
|
||||
#: contrib/sites/models.py:11
|
||||
msgid "display name"
|
||||
msgstr "nombre para mostrar"
|
||||
msgstr "nombre para visualizar"
|
||||
|
||||
#: contrib/sites/models.py:15
|
||||
msgid "site"
|
||||
@ -616,9 +627,9 @@ msgstr ""
|
||||
"<ul>\n"
|
||||
|
||||
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
|
||||
#: contrib/admin/filterspecs.py:143
|
||||
#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169
|
||||
msgid "All"
|
||||
msgstr "Todo"
|
||||
msgstr "Todos/as"
|
||||
|
||||
#: contrib/admin/filterspecs.py:109
|
||||
msgid "Any date"
|
||||
@ -680,7 +691,7 @@ msgstr "entrada de registro"
|
||||
msgid "log entries"
|
||||
msgstr "entradas de registro"
|
||||
|
||||
#: contrib/admin/templatetags/admin_list.py:228
|
||||
#: contrib/admin/templatetags/admin_list.py:230
|
||||
msgid "All dates"
|
||||
msgstr "Todas las fechas"
|
||||
|
||||
@ -752,12 +763,12 @@ msgstr "y"
|
||||
#: contrib/admin/views/main.py:338
|
||||
#, python-format
|
||||
msgid "Changed %s."
|
||||
msgstr "Modificado %s."
|
||||
msgstr "Modifica %s."
|
||||
|
||||
#: contrib/admin/views/main.py:340
|
||||
#, python-format
|
||||
msgid "Deleted %s."
|
||||
msgstr "Eliminado %s."
|
||||
msgstr "Elimina %s."
|
||||
|
||||
#: contrib/admin/views/main.py:343
|
||||
msgid "No fields changed."
|
||||
@ -802,82 +813,87 @@ msgstr "
|
||||
#: contrib/admin/views/main.py:533
|
||||
#, python-format
|
||||
msgid "Change history: %s"
|
||||
msgstr "Modificar histórico: %s"
|
||||
msgstr "Historia de modificaciones: %s"
|
||||
|
||||
#: contrib/admin/views/main.py:565
|
||||
#: contrib/admin/views/main.py:567
|
||||
#, python-format
|
||||
msgid "Select %s"
|
||||
msgstr "Seleccione %s"
|
||||
|
||||
#: contrib/admin/views/main.py:565
|
||||
#: contrib/admin/views/main.py:567
|
||||
#, python-format
|
||||
msgid "Select %s to change"
|
||||
msgstr "Seleccione %s para modificar"
|
||||
msgstr "Seleccione %s a modificar"
|
||||
|
||||
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
|
||||
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
|
||||
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
|
||||
#: contrib/admin/views/main.py:743
|
||||
msgid "Database error"
|
||||
msgstr "Error de base de datos"
|
||||
|
||||
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:289
|
||||
#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:297
|
||||
#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:300
|
||||
msgid "Integer"
|
||||
msgstr "Entero"
|
||||
|
||||
#: contrib/admin/views/doc.py:278
|
||||
#: contrib/admin/views/doc.py:280
|
||||
msgid "Boolean (Either True or False)"
|
||||
msgstr "Booleano (Verdadero o Falso)"
|
||||
|
||||
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
||||
#: contrib/admin/views/doc.py:281 contrib/admin/views/doc.py:299
|
||||
#, python-format
|
||||
msgid "String (up to %(maxlength)s)"
|
||||
msgstr "Cadena (máximo %(maxlength)s)"
|
||||
|
||||
#: contrib/admin/views/doc.py:280
|
||||
#: contrib/admin/views/doc.py:282
|
||||
msgid "Comma-separated integers"
|
||||
msgstr "Enteros separados por comas"
|
||||
|
||||
#: contrib/admin/views/doc.py:281
|
||||
#: contrib/admin/views/doc.py:283
|
||||
msgid "Date (without time)"
|
||||
msgstr "Fecha (sin hora)"
|
||||
|
||||
#: contrib/admin/views/doc.py:282
|
||||
#: contrib/admin/views/doc.py:284
|
||||
msgid "Date (with time)"
|
||||
msgstr "Fecha (con hora)"
|
||||
|
||||
#: contrib/admin/views/doc.py:283
|
||||
#: contrib/admin/views/doc.py:285
|
||||
msgid "E-mail address"
|
||||
msgstr "Dirección de correo electrónico"
|
||||
|
||||
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
|
||||
#: contrib/admin/views/doc.py:286 contrib/admin/views/doc.py:287
|
||||
#: contrib/admin/views/doc.py:290
|
||||
msgid "File path"
|
||||
msgstr "Ruta de archivo"
|
||||
|
||||
#: contrib/admin/views/doc.py:285
|
||||
#: contrib/admin/views/doc.py:288
|
||||
msgid "Decimal number"
|
||||
msgstr "Número decimal"
|
||||
|
||||
#: contrib/admin/views/doc.py:291
|
||||
#: contrib/admin/views/doc.py:294
|
||||
msgid "Boolean (Either True, False or None)"
|
||||
msgstr "Booleano (Verdadero, Falso o Nulo)"
|
||||
|
||||
#: contrib/admin/views/doc.py:292
|
||||
#: contrib/admin/views/doc.py:295
|
||||
msgid "Relation to parent model"
|
||||
msgstr "Relación con el modelo padre"
|
||||
|
||||
#: contrib/admin/views/doc.py:293
|
||||
#: contrib/admin/views/doc.py:296
|
||||
msgid "Phone number"
|
||||
msgstr "Número de teléfono"
|
||||
|
||||
#: contrib/admin/views/doc.py:298
|
||||
#: contrib/admin/views/doc.py:301
|
||||
msgid "Text"
|
||||
msgstr "Texto"
|
||||
|
||||
#: contrib/admin/views/doc.py:299
|
||||
#: contrib/admin/views/doc.py:302
|
||||
msgid "Time"
|
||||
msgstr "Hora"
|
||||
|
||||
#: contrib/admin/views/doc.py:301
|
||||
#: contrib/admin/views/doc.py:304
|
||||
msgid "U.S. state (two uppercase letters)"
|
||||
msgstr "Estado de los EEUU (dos letras mayúsculas)"
|
||||
|
||||
#: contrib/admin/views/doc.py:302
|
||||
#: contrib/admin/views/doc.py:305
|
||||
msgid "XML text"
|
||||
msgstr "Texto XML"
|
||||
|
||||
@ -900,7 +916,7 @@ msgstr "Hora:"
|
||||
#: contrib/admin/templates/admin/object_history.html:3
|
||||
#: contrib/admin/templates/admin/change_list.html:5
|
||||
#: contrib/admin/templates/admin/change_form.html:10
|
||||
#: contrib/admin/templates/admin/base.html:23
|
||||
#: contrib/admin/templates/admin/base.html:24
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:3
|
||||
#: contrib/admin/templates/registration/password_change_done.html:3
|
||||
#: contrib/admin/templates/registration/password_change_form.html:3
|
||||
@ -911,7 +927,7 @@ msgstr "Documentaci
|
||||
#: contrib/admin/templates/admin/object_history.html:3
|
||||
#: contrib/admin/templates/admin/change_list.html:5
|
||||
#: contrib/admin/templates/admin/change_form.html:10
|
||||
#: contrib/admin/templates/admin/base.html:23
|
||||
#: contrib/admin/templates/admin/base.html:24
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:3
|
||||
#: contrib/admin/templates/registration/password_change_done.html:3
|
||||
#: contrib/admin/templates/registration/password_change_form.html:3
|
||||
@ -932,8 +948,9 @@ msgstr "Cambiar contrase
|
||||
#: contrib/admin/templates/admin/change_list.html:6
|
||||
#: contrib/admin/templates/admin/500.html:4
|
||||
#: contrib/admin/templates/admin/change_form.html:13
|
||||
#: contrib/admin/templates/admin/base.html:28
|
||||
#: contrib/admin/templates/admin/base.html:29
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:6
|
||||
#: contrib/admin/templates/admin/invalid_setup.html:4
|
||||
#: contrib/admin/templates/registration/password_change_done.html:4
|
||||
#: contrib/admin/templates/registration/password_reset_form.html:4
|
||||
#: contrib/admin/templates/registration/logged_out.html:4
|
||||
@ -946,7 +963,7 @@ msgstr "Inicio"
|
||||
#: contrib/admin/templates/admin/object_history.html:5
|
||||
#: contrib/admin/templates/admin/change_form.html:20
|
||||
msgid "History"
|
||||
msgstr "Histórico"
|
||||
msgstr "Historia"
|
||||
|
||||
#: contrib/admin/templates/admin/object_history.html:18
|
||||
msgid "Date/time"
|
||||
@ -962,15 +979,15 @@ msgstr "Acci
|
||||
|
||||
#: contrib/admin/templates/admin/object_history.html:26
|
||||
msgid "DATE_WITH_TIME_FULL"
|
||||
msgstr ""
|
||||
msgstr "j M Y P"
|
||||
|
||||
#: contrib/admin/templates/admin/object_history.html:36
|
||||
msgid ""
|
||||
"This object doesn't have a change history. It probably wasn't added via this "
|
||||
"admin site."
|
||||
msgstr ""
|
||||
"Este objeto no tiene histórico de cambios. Probablemente no fue añadido "
|
||||
"usando este sitio de administración."
|
||||
"Este objeto no tiene historia de modificaciones. Probablemente no fue "
|
||||
"añadido usando este sitio de administración."
|
||||
|
||||
#: contrib/admin/templates/admin/change_list.html:11
|
||||
#, python-format
|
||||
@ -1007,6 +1024,22 @@ msgstr ""
|
||||
msgid "Go"
|
||||
msgstr "Buscar"
|
||||
|
||||
#: contrib/admin/templates/admin/search_form.html:10
|
||||
#, python-format
|
||||
msgid "1 result"
|
||||
msgid_plural "%(counter)s results"
|
||||
msgstr[0] "un resultado"
|
||||
msgstr[1] "%(counter)s resultados"
|
||||
|
||||
#: contrib/admin/templates/admin/search_form.html:10
|
||||
#, python-format
|
||||
msgid "%(full_result_count)s total"
|
||||
msgstr "total: %(full_result_count)s"
|
||||
|
||||
#: contrib/admin/templates/admin/pagination.html:10
|
||||
msgid "Show all"
|
||||
msgstr "Mostrar todos/as"
|
||||
|
||||
#: contrib/admin/templates/admin/base_site.html:4
|
||||
msgid "Django site admin"
|
||||
msgstr "Sitio de administración de Django"
|
||||
@ -1018,7 +1051,7 @@ msgstr "Administraci
|
||||
#: contrib/admin/templates/admin/index.html:17
|
||||
#, python-format
|
||||
msgid "Models available in the %(name)s application."
|
||||
msgstr "Modelos disponibles en la aplciación %(name)s."
|
||||
msgstr "Modelos disponibles en la aplicación %(name)s."
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:28
|
||||
#: contrib/admin/templates/admin/change_form.html:15
|
||||
@ -1043,7 +1076,7 @@ msgstr "Mis acciones"
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:57
|
||||
msgid "None available"
|
||||
msgstr "Ninguno disponible"
|
||||
msgstr "Ninguna disponible"
|
||||
|
||||
#: contrib/admin/templates/admin/404.html:4
|
||||
#: contrib/admin/templates/admin/404.html:8
|
||||
@ -1058,6 +1091,10 @@ msgstr "Lo sentimos, pero no se encuentra la p
|
||||
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
||||
msgstr "¿Ha <a href=\"/password_reset/\">olvidado su contraseña</a>?"
|
||||
|
||||
#: contrib/admin/templates/admin/filters.html:4
|
||||
msgid "Filter"
|
||||
msgstr "Filtrar"
|
||||
|
||||
#: contrib/admin/templates/admin/change_form.html:21
|
||||
msgid "View on site"
|
||||
msgstr "Ver en el sitio"
|
||||
@ -1076,7 +1113,7 @@ msgstr "Ordenaci
|
||||
msgid "Order:"
|
||||
msgstr "Orden:"
|
||||
|
||||
#: contrib/admin/templates/admin/base.html:23
|
||||
#: contrib/admin/templates/admin/base.html:24
|
||||
msgid "Welcome,"
|
||||
msgstr "Bienvenido,"
|
||||
|
||||
@ -1125,6 +1162,16 @@ msgstr "Grabar y continuar editando"
|
||||
msgid "Save"
|
||||
msgstr "Grabar"
|
||||
|
||||
#: contrib/admin/templates/admin/invalid_setup.html:8
|
||||
msgid ""
|
||||
"Something's wrong with your database installation. Make sure the appropriate "
|
||||
"database tables have been created, and make sure the database is readable by "
|
||||
"the appropriate user."
|
||||
msgstr ""
|
||||
"hay algún problema con su instalación de base de datos. Asegúrese de que las "
|
||||
"tablas de la misma hayan sido creadas, y asegúrese de que el usuario "
|
||||
"apropiado tenga permisos de escritura en la base de datos."
|
||||
|
||||
#: contrib/admin/templates/registration/password_change_done.html:4
|
||||
#: contrib/admin/templates/registration/password_change_form.html:4
|
||||
#: contrib/admin/templates/registration/password_change_form.html:6
|
||||
@ -1312,17 +1359,25 @@ msgid "As above, but opens the admin page in a new window."
|
||||
msgstr ""
|
||||
"Como antes, pero abre la página de administración en una nueva ventana."
|
||||
|
||||
#: utils/translation.py:360
|
||||
#: utils/translation.py:363
|
||||
msgid "DATE_FORMAT"
|
||||
msgstr ""
|
||||
msgstr "j N Y"
|
||||
|
||||
#: utils/translation.py:361
|
||||
#: utils/translation.py:364
|
||||
msgid "DATETIME_FORMAT"
|
||||
msgstr ""
|
||||
msgstr "j N Y P"
|
||||
|
||||
#: utils/translation.py:362
|
||||
#: utils/translation.py:365
|
||||
msgid "TIME_FORMAT"
|
||||
msgstr ""
|
||||
msgstr "P"
|
||||
|
||||
#: utils/translation.py:381
|
||||
msgid "YEAR_MONTH_FORMAT"
|
||||
msgstr "F Y"
|
||||
|
||||
#: utils/translation.py:382
|
||||
msgid "MONTH_DAY_FORMAT"
|
||||
msgstr "j \\de F"
|
||||
|
||||
#: utils/dates.py:6
|
||||
msgid "Monday"
|
||||
@ -1386,7 +1441,7 @@ msgstr "Agosto"
|
||||
|
||||
#: utils/dates.py:15
|
||||
msgid "September"
|
||||
msgstr "Septiembre"
|
||||
msgstr "Setiembre"
|
||||
|
||||
#: utils/dates.py:15
|
||||
msgid "October"
|
||||
@ -1430,11 +1485,11 @@ msgstr ""
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "aug"
|
||||
msgstr ""
|
||||
msgstr "ago"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "sep"
|
||||
msgstr ""
|
||||
msgstr "set"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "oct"
|
||||
@ -1450,11 +1505,11 @@ msgstr "dic"
|
||||
|
||||
#: utils/dates.py:27
|
||||
msgid "Jan."
|
||||
msgstr "Ene."
|
||||
msgstr "Enero"
|
||||
|
||||
#: utils/dates.py:27
|
||||
msgid "Feb."
|
||||
msgstr "Feb."
|
||||
msgstr ""
|
||||
|
||||
#: utils/dates.py:28
|
||||
msgid "Aug."
|
||||
@ -1462,15 +1517,15 @@ msgstr "Ago."
|
||||
|
||||
#: utils/dates.py:28
|
||||
msgid "Sept."
|
||||
msgstr "Sept."
|
||||
msgstr "Set."
|
||||
|
||||
#: utils/dates.py:28
|
||||
msgid "Oct."
|
||||
msgstr "Oct."
|
||||
msgstr ""
|
||||
|
||||
#: utils/dates.py:28
|
||||
msgid "Nov."
|
||||
msgstr "Nov."
|
||||
msgstr ""
|
||||
|
||||
#: utils/dates.py:28
|
||||
msgid "Dec."
|
||||
@ -1491,7 +1546,7 @@ msgstr[1] "meses"
|
||||
#: utils/timesince.py:14
|
||||
msgid "week"
|
||||
msgid_plural "weeks"
|
||||
msgstr[0] "semmana"
|
||||
msgstr[0] "semana"
|
||||
msgstr[1] "semanas"
|
||||
|
||||
#: utils/timesince.py:15
|
||||
@ -1546,7 +1601,7 @@ msgstr "Espa
|
||||
|
||||
#: conf/global_settings.py:45
|
||||
msgid "Argentinean Spanish"
|
||||
msgstr ""
|
||||
msgstr "Español Argentino"
|
||||
|
||||
#: conf/global_settings.py:46
|
||||
msgid "French"
|
||||
@ -1558,7 +1613,7 @@ msgstr "Gallego"
|
||||
|
||||
#: conf/global_settings.py:48
|
||||
msgid "Hungarian"
|
||||
msgstr ""
|
||||
msgstr "Húngaro"
|
||||
|
||||
#: conf/global_settings.py:49
|
||||
msgid "Hebrew"
|
||||
@ -1636,7 +1691,7 @@ msgid "%(optname)s with this %(fieldname)s already exists."
|
||||
msgstr "Ya existe %(optname)s con este %(fieldname)s."
|
||||
|
||||
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
|
||||
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
|
||||
#: db/models/fields/__init__.py:545 db/models/fields/__init__.py:556
|
||||
#: forms/__init__.py:346
|
||||
msgid "This field is required."
|
||||
msgstr "Este campo es obligatorio."
|
||||
@ -1653,11 +1708,11 @@ msgstr "Este valor debe ser True o False."
|
||||
msgid "This field cannot be null."
|
||||
msgstr "Este campo no puede ser nulo."
|
||||
|
||||
#: db/models/fields/__init__.py:468 core/validators.py:132
|
||||
#: db/models/fields/__init__.py:471 core/validators.py:135
|
||||
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
||||
msgstr "Introduzca una fecha/hora válida en formato YYYY-MM-DD HH:MM."
|
||||
|
||||
#: db/models/fields/__init__.py:562
|
||||
#: db/models/fields/__init__.py:565
|
||||
msgid "Enter a valid filename."
|
||||
msgstr "Introduzca un nombre de achivo válido"
|
||||
|
||||
@ -1688,43 +1743,48 @@ msgstr[1] ""
|
||||
"Por favor, introduzca IDs de %(self)s válidos. Los valores %(value)r no son "
|
||||
"válidos."
|
||||
|
||||
#: forms/__init__.py:380
|
||||
#: forms/__init__.py:381
|
||||
#, python-format
|
||||
msgid "Ensure your text is less than %s character."
|
||||
msgid_plural "Ensure your text is less than %s characters."
|
||||
msgstr[0] "Asegúrese de que su texto tiene menos de %s carácter."
|
||||
msgstr[1] "Asegúrese de que su texto tiene menos de %s caracteres."
|
||||
|
||||
#: forms/__init__.py:385
|
||||
#: forms/__init__.py:386
|
||||
msgid "Line breaks are not allowed here."
|
||||
msgstr "No se permiten saltos de línea."
|
||||
|
||||
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
|
||||
#: forms/__init__.py:485 forms/__init__.py:558 forms/__init__.py:597
|
||||
#, python-format
|
||||
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
|
||||
msgstr "Seleccione una opción válida; '%(data)s' no está en %(choices)s."
|
||||
|
||||
#: forms/__init__.py:645
|
||||
#: forms/__init__.py:659 core/validators.py:151 core/validators.py:379
|
||||
msgid "No file was submitted. Check the encoding type on the form."
|
||||
msgstr ""
|
||||
"No se envió un archivo. Verifique el tipo de codificación en el formulario."
|
||||
|
||||
#: forms/__init__.py:661
|
||||
msgid "The submitted file is empty."
|
||||
msgstr "El archivo enviado está vacío."
|
||||
|
||||
#: forms/__init__.py:699
|
||||
#: forms/__init__.py:717
|
||||
msgid "Enter a whole number between -32,768 and 32,767."
|
||||
msgstr "Introduzca un número entero entre -32,768 y 32,767."
|
||||
|
||||
#: forms/__init__.py:708
|
||||
#: forms/__init__.py:727
|
||||
msgid "Enter a positive number."
|
||||
msgstr "Introduzca un número positivo."
|
||||
|
||||
#: forms/__init__.py:717
|
||||
#: forms/__init__.py:737
|
||||
msgid "Enter a whole number between 0 and 32,767."
|
||||
msgstr "Introduzca un número entero entre 0 y 32,767."
|
||||
|
||||
#: core/validators.py:60
|
||||
#: core/validators.py:63
|
||||
msgid "This value must contain only letters, numbers and underscores."
|
||||
msgstr "Este valor debe contener sólo letras, números y guiones bajos."
|
||||
|
||||
#: core/validators.py:64
|
||||
#: core/validators.py:67
|
||||
msgid ""
|
||||
"This value must contain only letters, numbers, underscores, dashes or "
|
||||
"slashes."
|
||||
@ -1732,59 +1792,59 @@ msgstr ""
|
||||
"Este valor debe contener sólo letras, números, guiones bajos, barras (/) o "
|
||||
"slashes."
|
||||
|
||||
#: core/validators.py:72
|
||||
#: core/validators.py:75
|
||||
msgid "Uppercase letters are not allowed here."
|
||||
msgstr "No se admiten letras mayúsculas."
|
||||
|
||||
#: core/validators.py:76
|
||||
#: core/validators.py:79
|
||||
msgid "Lowercase letters are not allowed here."
|
||||
msgstr "No se admiten letras minúsculas."
|
||||
|
||||
#: core/validators.py:83
|
||||
#: core/validators.py:86
|
||||
msgid "Enter only digits separated by commas."
|
||||
msgstr "Introduzca sólo dígitos separados por comas."
|
||||
|
||||
#: core/validators.py:95
|
||||
#: core/validators.py:98
|
||||
msgid "Enter valid e-mail addresses separated by commas."
|
||||
msgstr "Introduzca direcciones de correo válidas separadas por comas."
|
||||
|
||||
#: core/validators.py:99
|
||||
#: core/validators.py:102
|
||||
msgid "Please enter a valid IP address."
|
||||
msgstr "Por favor introduzca una dirección IP válida."
|
||||
|
||||
#: core/validators.py:103
|
||||
#: core/validators.py:106
|
||||
msgid "Empty values are not allowed here."
|
||||
msgstr "No se admiten valores vacíos."
|
||||
|
||||
#: core/validators.py:107
|
||||
#: core/validators.py:110
|
||||
msgid "Non-numeric characters aren't allowed here."
|
||||
msgstr "No se admiten caracteres no numéricos."
|
||||
|
||||
#: core/validators.py:111
|
||||
#: core/validators.py:114
|
||||
msgid "This value can't be comprised solely of digits."
|
||||
msgstr "Este valor no puede estar formado sólo por dígitos."
|
||||
|
||||
#: core/validators.py:116
|
||||
#: core/validators.py:119
|
||||
msgid "Enter a whole number."
|
||||
msgstr "Introduzca un número entero."
|
||||
|
||||
#: core/validators.py:120
|
||||
#: core/validators.py:123
|
||||
msgid "Only alphabetical characters are allowed here."
|
||||
msgstr "Sólo se admiten caracteres alfabéticos."
|
||||
|
||||
#: core/validators.py:124
|
||||
#: core/validators.py:127
|
||||
msgid "Enter a valid date in YYYY-MM-DD format."
|
||||
msgstr "Introduzca una fecha válida en formato AAAA-MM-DD."
|
||||
|
||||
#: core/validators.py:128
|
||||
#: core/validators.py:131
|
||||
msgid "Enter a valid time in HH:MM format."
|
||||
msgstr "Introduzca una hora válida en formato HH:MM."
|
||||
|
||||
#: core/validators.py:136
|
||||
#: core/validators.py:139
|
||||
msgid "Enter a valid e-mail address."
|
||||
msgstr "Introduzca una dirección de correo electrónico válida"
|
||||
|
||||
#: core/validators.py:148
|
||||
#: core/validators.py:155
|
||||
msgid ""
|
||||
"Upload a valid image. The file you uploaded was either not an image or a "
|
||||
"corrupted image."
|
||||
@ -1792,28 +1852,28 @@ msgstr ""
|
||||
"Envíe una imagen válida. El archivo que ha enviado no era una imagen o se "
|
||||
"trataba de una imagen corrupta."
|
||||
|
||||
#: core/validators.py:155
|
||||
#: core/validators.py:162
|
||||
#, python-format
|
||||
msgid "The URL %s does not point to a valid image."
|
||||
msgstr "La URL %s no apunta a una imagen válida."
|
||||
|
||||
#: core/validators.py:159
|
||||
#: core/validators.py:166
|
||||
#, python-format
|
||||
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
|
||||
msgstr ""
|
||||
"Los números de teléfono deben guardar el formato XXX-XXX-XXXX format. \"%s\" "
|
||||
"no es válido."
|
||||
|
||||
#: core/validators.py:167
|
||||
#: core/validators.py:174
|
||||
#, python-format
|
||||
msgid "The URL %s does not point to a valid QuickTime video."
|
||||
msgstr "La URL %s no apunta a un vídeo QuickTime válido."
|
||||
|
||||
#: core/validators.py:171
|
||||
#: core/validators.py:178
|
||||
msgid "A valid URL is required."
|
||||
msgstr "Se precisa una URL válida."
|
||||
|
||||
#: core/validators.py:185
|
||||
#: core/validators.py:192
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Valid HTML is required. Specific errors are:\n"
|
||||
@ -1822,116 +1882,129 @@ msgstr ""
|
||||
"Se precisa HTML válido. Los errores específicos son:\n"
|
||||
"%s"
|
||||
|
||||
#: core/validators.py:192
|
||||
#: core/validators.py:199
|
||||
#, python-format
|
||||
msgid "Badly formed XML: %s"
|
||||
msgstr "XML mal formado: %s"
|
||||
|
||||
#: core/validators.py:202
|
||||
#: core/validators.py:209
|
||||
#, python-format
|
||||
msgid "Invalid URL: %s"
|
||||
msgstr "URL no válida: %s"
|
||||
|
||||
#: core/validators.py:206 core/validators.py:208
|
||||
#: core/validators.py:213 core/validators.py:215
|
||||
#, python-format
|
||||
msgid "The URL %s is a broken link."
|
||||
msgstr "La URL %s es un enlace roto."
|
||||
|
||||
#: core/validators.py:214
|
||||
#: core/validators.py:221
|
||||
msgid "Enter a valid U.S. state abbreviation."
|
||||
msgstr "Introduzca una abreviatura válida de estado de los EEUU."
|
||||
|
||||
#: core/validators.py:229
|
||||
#: core/validators.py:236
|
||||
#, python-format
|
||||
msgid "Watch your mouth! The word %s is not allowed here."
|
||||
msgid_plural "Watch your mouth! The words %s are not allowed here."
|
||||
msgstr[0] "¡Vigila tu boca! Aquí no admitimos la palabra %s."
|
||||
msgstr[1] "¡Vigila tu boca! Aquí no admitimos las palabras %s."
|
||||
|
||||
#: core/validators.py:236
|
||||
#: core/validators.py:243
|
||||
#, python-format
|
||||
msgid "This field must match the '%s' field."
|
||||
msgstr "Este campo debe concordar con el campo '%s'."
|
||||
|
||||
#: core/validators.py:255
|
||||
#: core/validators.py:262
|
||||
msgid "Please enter something for at least one field."
|
||||
msgstr "Por favor, introduzca algo en al menos un campo."
|
||||
|
||||
#: core/validators.py:264 core/validators.py:275
|
||||
#: core/validators.py:271 core/validators.py:282
|
||||
msgid "Please enter both fields or leave them both empty."
|
||||
msgstr "Por favor, rellene ambos campos o deje ambos vacíos."
|
||||
|
||||
#: core/validators.py:282
|
||||
#: core/validators.py:289
|
||||
#, python-format
|
||||
msgid "This field must be given if %(field)s is %(value)s"
|
||||
msgstr "Se debe proporcionar este campo si %(field)s es %(value)s"
|
||||
|
||||
#: core/validators.py:294
|
||||
#: core/validators.py:301
|
||||
#, python-format
|
||||
msgid "This field must be given if %(field)s is not %(value)s"
|
||||
msgstr "Se debe proporcionar este campo si %(field)s no es %(value)s"
|
||||
|
||||
#: core/validators.py:313
|
||||
#: core/validators.py:320
|
||||
msgid "Duplicate values are not allowed."
|
||||
msgstr "No se admiten valores duplicados."
|
||||
|
||||
#: core/validators.py:336
|
||||
#: core/validators.py:343
|
||||
#, python-format
|
||||
msgid "This value must be a power of %s."
|
||||
msgstr "Este valor debe ser una potencia de %s."
|
||||
|
||||
#: core/validators.py:347
|
||||
#: core/validators.py:354
|
||||
msgid "Please enter a valid decimal number."
|
||||
msgstr "Por favor, introduzca un número decimal válido."
|
||||
|
||||
#: core/validators.py:349
|
||||
#: core/validators.py:356
|
||||
#, python-format
|
||||
msgid "Please enter a valid decimal number with at most %s total digit."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with at most %s total digits."
|
||||
msgstr[0] ""
|
||||
"Por favor, introduzca un número decimal válido con con un máximo de %s "
|
||||
"Por favor, introduzca un número decimal válido con con un máximo de un "
|
||||
"dígito en total."
|
||||
msgstr[1] ""
|
||||
"Por favor, introduzca un número decimal válido con un maximo de %s dígitos "
|
||||
"en total."
|
||||
|
||||
#: core/validators.py:352
|
||||
#: core/validators.py:359
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please enter a valid decimal number with a whole part of at most %s digit."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with a whole part of at most %s digits."
|
||||
msgstr[0] ""
|
||||
"Por favor, introduzca un número decimal válido con un dígito entero como "
|
||||
"máximo."
|
||||
msgstr[1] ""
|
||||
"Por favor, introduzca un número decimal válido con un máximo de %s dígitos "
|
||||
"enteros."
|
||||
|
||||
#: core/validators.py:362
|
||||
#, python-format
|
||||
msgid "Please enter a valid decimal number with at most %s decimal place."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with at most %s decimal places."
|
||||
msgstr[0] ""
|
||||
"Por favor, introduzca un número decimal válido con un máximo de %s "
|
||||
"posición decimal."
|
||||
"Por favor, introduzca un número decimal válido con un máximo de una posición "
|
||||
"decimal."
|
||||
msgstr[1] ""
|
||||
"Por favor, introduzca un número decimal válido con un máximo de %s "
|
||||
"posiciones decimales."
|
||||
|
||||
#: core/validators.py:362
|
||||
#: core/validators.py:372
|
||||
#, python-format
|
||||
msgid "Make sure your uploaded file is at least %s bytes big."
|
||||
msgstr "Asegúrese de que el archivo que envía tiene al menos %s bytes."
|
||||
|
||||
#: core/validators.py:363
|
||||
#: core/validators.py:373
|
||||
#, python-format
|
||||
msgid "Make sure your uploaded file is at most %s bytes big."
|
||||
msgstr "Asegúrese de que el archivo que envía tiene como máximo %s bytes."
|
||||
|
||||
#: core/validators.py:376
|
||||
#: core/validators.py:390
|
||||
msgid "The format for this field is wrong."
|
||||
msgstr "El formato de este campo es incorrecto."
|
||||
|
||||
#: core/validators.py:391
|
||||
#: core/validators.py:405
|
||||
msgid "This field is invalid."
|
||||
msgstr "Este campo no es válido."
|
||||
|
||||
#: core/validators.py:426
|
||||
#: core/validators.py:441
|
||||
#, python-format
|
||||
msgid "Could not retrieve anything from %s."
|
||||
msgstr "No pude obtener nada de %s."
|
||||
|
||||
#: core/validators.py:429
|
||||
#: core/validators.py:444
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
||||
@ -1939,7 +2012,7 @@ msgstr ""
|
||||
"La URL %(url)s devolvió la cabecera Content-Type '%(contenttype)s', que no "
|
||||
"es válida."
|
||||
|
||||
#: core/validators.py:462
|
||||
#: core/validators.py:477
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
|
||||
@ -1948,7 +2021,7 @@ msgstr ""
|
||||
"Por favor, cierre la etiqueta %(tag)s de la línea %(line)s. (La línea "
|
||||
"empieza por \"%(start)s\".)"
|
||||
|
||||
#: core/validators.py:466
|
||||
#: core/validators.py:481
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Some text starting on line %(line)s is not allowed in that context. (Line "
|
||||
@ -1957,7 +2030,7 @@ msgstr ""
|
||||
"Parte del texto que comienza en la línea %(line)s no está permitido en ese "
|
||||
"contexto. (La línea empieza por \"%(start)s\".)"
|
||||
|
||||
#: core/validators.py:471
|
||||
#: core/validators.py:486
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
|
||||
@ -1966,7 +2039,7 @@ msgstr ""
|
||||
"El \"%(attr)s\" de la línea %(line)s no es un atributo válido. (La línea "
|
||||
"empieza por \"%(start)s\".)"
|
||||
|
||||
#: core/validators.py:476
|
||||
#: core/validators.py:491
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
|
||||
@ -1975,7 +2048,7 @@ msgstr ""
|
||||
"La \"<%(tag)s>\" de la línea %(line)s no es una etiqueta válida. (La línea "
|
||||
"empieza por \"%(start)s\".)"
|
||||
|
||||
#: core/validators.py:480
|
||||
#: core/validators.py:495
|
||||
#, python-format
|
||||
msgid ""
|
||||
"A tag on line %(line)s is missing one or more required attributes. (Line "
|
||||
@ -1984,7 +2057,7 @@ msgstr ""
|
||||
"A una etiqueta de la línea %(line)s le faltan uno o más atributos "
|
||||
"requeridos. (La línea empieza por \"%(start)s\".)"
|
||||
|
||||
#: core/validators.py:485
|
||||
#: core/validators.py:500
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
|
||||
@ -1993,10 +2066,23 @@ msgstr ""
|
||||
"El atributo \"%(attr)s\" de la línea %(line)s tiene un valor que no es "
|
||||
"válido. (La línea empieza por \"%(start)s\".)"
|
||||
|
||||
#: template/defaultfilters.py:379
|
||||
#: template/defaultfilters.py:389
|
||||
msgid "yes,no,maybe"
|
||||
msgstr "si,no,tal vez"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%(content_type_name)s"
|
||||
#~ msgstr "tipos de contenido"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "%(myname)s"
|
||||
#~ msgstr "Agregar %(name)s"
|
||||
|
||||
#~ msgid "%(result_count)s result"
|
||||
#~ msgid_plural "%(counter)s results"
|
||||
#~ msgstr[0] "un resultado"
|
||||
#~ msgstr[1] "%(counter)s resultados"
|
||||
|
||||
#~ msgid "Comment"
|
||||
#~ msgstr "Comentario"
|
||||
|
||||
@ -2014,16 +2100,3 @@ msgstr "si,no,tal vez"
|
||||
|
||||
#~ msgid "packages"
|
||||
#~ msgstr "paquetes"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Please enter a valid decimal number with a whole part of at most %s digit."
|
||||
#~ msgid_plural ""
|
||||
#~ "Please enter a valid decimal number with a whole part of at most %s "
|
||||
#~ "digits."
|
||||
#~ msgstr[0] ""
|
||||
#~ "Por favor, introduzca un número decimal válido con a lo más %s dígito en "
|
||||
#~ "total."
|
||||
#~ msgstr[1] ""
|
||||
#~ "Por favor, introduzca un número decimal válido con a lo más %s dígitos en "
|
||||
#~ "total."
|
||||
|
Binary file not shown.
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Django JavaScript 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
|
||||
"POT-Creation-Date: 2006-06-19 12:15-0300\n"
|
||||
"PO-Revision-Date: 2006-05-16 10:20-0300\n"
|
||||
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -22,7 +22,7 @@ msgstr "%s disponibles"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||
msgid "Choose all"
|
||||
msgstr "Selecciona todos"
|
||||
msgstr "Seleccionar todos"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||
msgid "Add"
|
||||
@ -43,9 +43,9 @@ msgstr "Haga sus elecciones y haga click en "
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||
msgid "Clear all"
|
||||
msgstr "Elimina todos"
|
||||
msgstr "Eliminar todos"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:26
|
||||
#: contrib/admin/media/js/dateparse.js:32
|
||||
#: contrib/admin/media/js/calendar.js:24
|
||||
msgid ""
|
||||
"January February March April May June July August September October November "
|
||||
@ -54,7 +54,7 @@ msgstr ""
|
||||
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre "
|
||||
"Noviembre Diciembre"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:27
|
||||
#: contrib/admin/media/js/dateparse.js:33
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||
msgstr "Domingo Lunes Martes Miércoles Jueves Viernes Sábado"
|
||||
|
||||
@ -62,8 +62,17 @@ msgstr "Domingo Lunes Martes Mi
|
||||
msgid "S M T W T F S"
|
||||
msgstr "D L M M J V S"
|
||||
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||
msgid "Show"
|
||||
msgstr "Mostrar"
|
||||
|
||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||
msgid "Hide"
|
||||
msgstr "Ocultar"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:89
|
||||
msgid "Now"
|
||||
msgstr "Ahora"
|
||||
|
||||
@ -71,40 +80,40 @@ msgstr "Ahora"
|
||||
msgid "Clock"
|
||||
msgstr "Reloj"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:86
|
||||
msgid "Choose a time"
|
||||
msgstr "Elija una hora"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:90
|
||||
msgid "Midnight"
|
||||
msgstr "Medianoche"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:91
|
||||
msgid "6 a.m."
|
||||
msgstr "6 a.m."
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:92
|
||||
msgid "Noon"
|
||||
msgstr "Mediodía"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:96
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:187
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:120
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:181
|
||||
msgid "Today"
|
||||
msgstr "Hoy"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:123
|
||||
msgid "Calendar"
|
||||
msgstr "Calendario"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||
msgid "Yesterday"
|
||||
msgstr "Ayer"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||
msgid "Tomorrow"
|
||||
msgstr "Mañana"
|
||||
|
Binary file not shown.
@ -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
|
||||
|
Binary file not shown.
@ -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 ""
|
||||
|
Binary file not shown.
@ -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
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ta/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/ta/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2111
django/conf/locale/ta/LC_MESSAGES/django.po
Normal file
2111
django/conf/locale/ta/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
107
django/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
Normal file
107
django/conf/locale/zh_CN/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,107 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-03-21 18:43+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <max@exoweb.net>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||
msgid "Available %s"
|
||||
msgstr "可行 %s"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||
msgid "Choose all"
|
||||
msgstr "全选"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||
msgid "Add"
|
||||
msgstr "增加"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||
msgid "Remove"
|
||||
msgstr "移出"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||
msgid "Chosen %s"
|
||||
msgstr "选择 %s"
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||
msgid "Select your choice(s) and click "
|
||||
msgstr "挑选你的选择并且点击 "
|
||||
|
||||
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||
msgid "Clear all"
|
||||
msgstr "清除所有"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:32
|
||||
#: contrib/admin/media/js/calendar.js:24
|
||||
msgid ""
|
||||
"January February March April May June July August September October November "
|
||||
"December"
|
||||
msgstr "一月 二月 三月 四月 五月 六月 六月 七月 八月 九月 十月 十一月 十二月"
|
||||
|
||||
#: contrib/admin/media/js/dateparse.js:33
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||
msgstr "星期天 星期一 星期二 星期三 星期四 星期五 星期六"
|
||||
|
||||
#: contrib/admin/media/js/calendar.js:25
|
||||
msgid "S M T W T F S"
|
||||
msgstr "日 月 火 水 木 金 土"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||
msgid "Now"
|
||||
msgstr "现在"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||
msgid "Clock"
|
||||
msgstr "时钟"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||
msgid "Choose a time"
|
||||
msgstr "选择一个时间"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||
msgid "Midnight"
|
||||
msgstr "午夜"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||
msgid "6 a.m."
|
||||
msgstr "上午6点"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||
msgid "Noon"
|
||||
msgstr "正午"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||
msgid "Today"
|
||||
msgstr "今天"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||
msgid "Calendar"
|
||||
msgstr "日历"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||
msgid "Yesterday"
|
||||
msgstr "昨天"
|
||||
|
||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||
msgid "Tomorrow"
|
||||
msgstr "明天"
|
@ -10,8 +10,10 @@ include = lambda urlconf_module: [urlconf_module]
|
||||
def patterns(prefix, *tuples):
|
||||
pattern_list = []
|
||||
for t in tuples:
|
||||
if type(t[1]) == list:
|
||||
pattern_list.append(RegexURLResolver(t[0], t[1][0]))
|
||||
regex, view_or_include = t[:2]
|
||||
default_kwargs = t[2:]
|
||||
if type(view_or_include) == list:
|
||||
pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs))
|
||||
else:
|
||||
pattern_list.append(RegexURLPattern(t[0], prefix and (prefix + '.' + t[1]) or t[1], *t[2:]))
|
||||
pattern_list.append(RegexURLPattern(regex, prefix and (prefix + '.' + view_or_include) or view_or_include, *default_kwargs))
|
||||
return pattern_list
|
||||
|
@ -123,7 +123,7 @@ class DateFieldFilterSpec(FilterSpec):
|
||||
def choices(self, cl):
|
||||
for title, param_dict in self.links:
|
||||
yield {'selected': self.date_params == param_dict,
|
||||
'query_string': cl.get_query_string(param_dict, self.field_generic),
|
||||
'query_string': cl.get_query_string(param_dict, [self.field_generic]),
|
||||
'display': title}
|
||||
|
||||
FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)
|
||||
|
@ -42,9 +42,9 @@
|
||||
|
||||
/* PAGINATOR */
|
||||
.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
|
||||
.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
|
||||
.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
|
||||
.paginator a.showall { padding:0 !important; border:none !important; }
|
||||
.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
|
||||
.paginator .end { border-width:2px !important; margin-right:6px; }
|
||||
.paginator .end { border-width:2px !important; margin-right:6px; }
|
||||
.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
|
||||
.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }
|
||||
|
@ -7,10 +7,10 @@
|
||||
form .form-row p { padding-left:0; font-size:11px; }
|
||||
|
||||
/* FORM LABELS */
|
||||
form h4 { margin:0 !important; padding:0 !important; border:none !important; }
|
||||
form h4 { margin:0 !important; padding:0 !important; border:none !important; }
|
||||
label { font-weight:normal !important; color:#666; font-size:12px; }
|
||||
label.inline { margin-left:20px; }
|
||||
.required label, label.required { font-weight:bold !important; color:#333 !important; }
|
||||
.required label, label.required { font-weight:bold !important; color:#333 !important; }
|
||||
|
||||
/* RADIO BUTTONS */
|
||||
form ul.radiolist li { list-style-type:none; }
|
||||
|
@ -31,7 +31,7 @@ fieldset { margin:0; padding:0; }
|
||||
blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
|
||||
code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
|
||||
pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
|
||||
code strong { color:#930; }
|
||||
code strong { color:#930; }
|
||||
hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
|
||||
|
||||
/* TEXT STYLES & MODIFIERS */
|
||||
@ -81,7 +81,7 @@ table.orderable tbody tr td:first-child { padding-left:14px; background-image:ur
|
||||
table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; }
|
||||
|
||||
/* FORM DEFAULTS */
|
||||
input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
|
||||
input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
|
||||
textarea { vertical-align:top !important; }
|
||||
input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
|
||||
|
||||
@ -92,7 +92,7 @@ input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2
|
||||
input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; }
|
||||
|
||||
/* MODULES */
|
||||
.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
|
||||
.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
|
||||
.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
|
||||
.module blockquote { margin-left:12px; }
|
||||
.module ul, .module ol { margin-left:1.5em; }
|
||||
|
@ -4,7 +4,7 @@
|
||||
#header { width:100%; }
|
||||
#content-main { float:left; width:100%; }
|
||||
#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
|
||||
#footer { clear:both; padding:10px; }
|
||||
#footer { clear:both; padding:10px; }
|
||||
|
||||
/* COLUMN TYPES */
|
||||
.colMS { margin-right:20em !important; }
|
||||
@ -16,14 +16,14 @@
|
||||
.dashboard #content { width:500px; }
|
||||
|
||||
/* HEADER */
|
||||
#header { background:#417690; color:#ffc; overflow:hidden; }
|
||||
#header { background:#417690; color:#ffc; overflow:hidden; }
|
||||
#header a:link, #header a:visited { color:white; }
|
||||
#header a:hover { text-decoration:underline; }
|
||||
#branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; }
|
||||
#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
|
||||
#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
|
||||
#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
|
||||
|
||||
/* SIDEBAR */
|
||||
#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
|
||||
#content-related h4 { font-size:11px; }
|
||||
#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
|
||||
#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
|
@ -16,7 +16,7 @@ th { text-align: right; }
|
||||
|
||||
|
||||
/* layout styles */
|
||||
#user-tools { right:auto; left:0; text-align:left; }
|
||||
#user-tools { right:auto; left:0; text-align:left; }
|
||||
div.breadcrumbs { text-align:right; }
|
||||
#content-main { float:right;}
|
||||
#content-related { float:left; margin-left:-19em; margin-right:auto;}
|
||||
|
@ -3,83 +3,83 @@
|
||||
// link when the fieldset is visible.
|
||||
|
||||
function findForm(node) {
|
||||
// returns the node of the form containing the given node
|
||||
if (node.tagName.toLowerCase() != 'form') {
|
||||
return findForm(node.parentNode);
|
||||
}
|
||||
return node;
|
||||
// returns the node of the form containing the given node
|
||||
if (node.tagName.toLowerCase() != 'form') {
|
||||
return findForm(node.parentNode);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
var CollapsedFieldsets = {
|
||||
collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
|
||||
collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
|
||||
collapsed_class: 'collapsed',
|
||||
init: function() {
|
||||
var fieldsets = document.getElementsByTagName('fieldset');
|
||||
var collapsed_seen = false;
|
||||
for (var i = 0, fs; fs = fieldsets[i]; i++) {
|
||||
// Collapse this fieldset if it has the correct class, and if it
|
||||
// doesn't have any errors. (Collapsing shouldn't apply in the case
|
||||
// of error messages.)
|
||||
if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
|
||||
collapsed_seen = true;
|
||||
// Give it an additional class, used by CSS to hide it.
|
||||
fs.className += ' ' + CollapsedFieldsets.collapsed_class;
|
||||
// (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
|
||||
var collapse_link = document.createElement('a');
|
||||
collapse_link.className = 'collapse-toggle';
|
||||
collapse_link.id = 'fieldsetcollapser' + i;
|
||||
collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
|
||||
collapse_link.href = '#';
|
||||
collapse_link.innerHTML = gettext('Show');
|
||||
var h2 = fs.getElementsByTagName('h2')[0];
|
||||
h2.appendChild(document.createTextNode(' ('));
|
||||
h2.appendChild(collapse_link);
|
||||
h2.appendChild(document.createTextNode(')'));
|
||||
}
|
||||
}
|
||||
if (collapsed_seen) {
|
||||
// Expand all collapsed fieldsets when form is submitted.
|
||||
addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
|
||||
}
|
||||
},
|
||||
fieldset_has_errors: function(fs) {
|
||||
// Returns true if any fields in the fieldset have validation errors.
|
||||
var divs = fs.getElementsByTagName('div');
|
||||
for (var i=0; i<divs.length; i++) {
|
||||
if (divs[i].className.match(/\berror\b/)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
show: function(fieldset_index) {
|
||||
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
||||
// Remove the class name that causes the "display: none".
|
||||
fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
|
||||
// Toggle the "Show" link to a "Hide" link
|
||||
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
||||
collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
|
||||
collapse_link.innerHTML = gettext('Hide');
|
||||
},
|
||||
hide: function(fieldset_index) {
|
||||
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
||||
// Add the class name that causes the "display: none".
|
||||
fs.className += ' ' + CollapsedFieldsets.collapsed_class;
|
||||
// Toggle the "Hide" link to a "Show" link
|
||||
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
||||
collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with.
|
||||
collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden.
|
||||
collapsed_class: 'collapsed',
|
||||
init: function() {
|
||||
var fieldsets = document.getElementsByTagName('fieldset');
|
||||
var collapsed_seen = false;
|
||||
for (var i = 0, fs; fs = fieldsets[i]; i++) {
|
||||
// Collapse this fieldset if it has the correct class, and if it
|
||||
// doesn't have any errors. (Collapsing shouldn't apply in the case
|
||||
// of error messages.)
|
||||
if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) {
|
||||
collapsed_seen = true;
|
||||
// Give it an additional class, used by CSS to hide it.
|
||||
fs.className += ' ' + CollapsedFieldsets.collapsed_class;
|
||||
// (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>)
|
||||
var collapse_link = document.createElement('a');
|
||||
collapse_link.className = 'collapse-toggle';
|
||||
collapse_link.id = 'fieldsetcollapser' + i;
|
||||
collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
|
||||
collapse_link.href = '#';
|
||||
collapse_link.innerHTML = gettext('Show');
|
||||
var h2 = fs.getElementsByTagName('h2')[0];
|
||||
h2.appendChild(document.createTextNode(' ('));
|
||||
h2.appendChild(collapse_link);
|
||||
h2.appendChild(document.createTextNode(')'));
|
||||
}
|
||||
}
|
||||
if (collapsed_seen) {
|
||||
// Expand all collapsed fieldsets when form is submitted.
|
||||
addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); });
|
||||
}
|
||||
},
|
||||
fieldset_has_errors: function(fs) {
|
||||
// Returns true if any fields in the fieldset have validation errors.
|
||||
var divs = fs.getElementsByTagName('div');
|
||||
for (var i=0; i<divs.length; i++) {
|
||||
if (divs[i].className.match(/\berror\b/)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
show: function(fieldset_index) {
|
||||
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
||||
// Remove the class name that causes the "display: none".
|
||||
fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, '');
|
||||
// Toggle the "Show" link to a "Hide" link
|
||||
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
||||
collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
|
||||
collapse_link.innerHTML = gettext('Hide');
|
||||
},
|
||||
hide: function(fieldset_index) {
|
||||
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
||||
// Add the class name that causes the "display: none".
|
||||
fs.className += ' ' + CollapsedFieldsets.collapsed_class;
|
||||
// Toggle the "Hide" link to a "Show" link
|
||||
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
||||
collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
|
||||
collapse_link.innerHTML = gettext('Show');
|
||||
},
|
||||
collapse_link.innerHTML = gettext('Show');
|
||||
},
|
||||
|
||||
uncollapse_all: function() {
|
||||
var fieldsets = document.getElementsByTagName('fieldset');
|
||||
for (var i=0; i<fieldsets.length; i++) {
|
||||
if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
|
||||
CollapsedFieldsets.show(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
uncollapse_all: function() {
|
||||
var fieldsets = document.getElementsByTagName('fieldset');
|
||||
for (var i=0; i<fieldsets.length; i++) {
|
||||
if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) {
|
||||
CollapsedFieldsets.show(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addEvent(window, 'load', CollapsedFieldsets.init);
|
||||
|
@ -8,7 +8,9 @@ var DateTimeShortcuts = {
|
||||
clockInputs: [],
|
||||
calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
|
||||
calendarDivName2: 'calendarin', // name of <div> that contains calendar
|
||||
calendarLinkName: 'calendarlink',// name of the link that is used to toggle
|
||||
clockDivName: 'clockbox', // name of clock <div> that gets toggled
|
||||
clockLinkName: 'clocklink', // name of the link that is used to toggle
|
||||
admin_media_prefix: '',
|
||||
init: function() {
|
||||
// Deduce admin_media_prefix by looking at the <script>s in the
|
||||
@ -46,6 +48,7 @@ var DateTimeShortcuts = {
|
||||
now_link.appendChild(document.createTextNode(gettext('Now')));
|
||||
var clock_link = document.createElement('a');
|
||||
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
|
||||
clock_link.id = DateTimeShortcuts.clockLinkName + num;
|
||||
quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
|
||||
shortcuts_span.appendChild(document.createTextNode('\240'));
|
||||
shortcuts_span.appendChild(now_link);
|
||||
@ -69,17 +72,6 @@ var DateTimeShortcuts = {
|
||||
var clock_box = document.createElement('div');
|
||||
clock_box.style.display = 'none';
|
||||
clock_box.style.position = 'absolute';
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
clock_box.style.left = findPosX(clock_link) - 110 + 'px';
|
||||
}
|
||||
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
||||
clock_box.className = 'clockbox module';
|
||||
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
||||
document.body.appendChild(clock_box);
|
||||
@ -98,7 +90,25 @@ var DateTimeShortcuts = {
|
||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
|
||||
},
|
||||
openClock: function(num) {
|
||||
document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'block';
|
||||
var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
|
||||
var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
|
||||
|
||||
// Recalculate the clockbox position
|
||||
// is it left-to-right or right-to-left layout ?
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
clock_box.style.left = findPosX(clock_link) - 110 + 'px';
|
||||
}
|
||||
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
||||
|
||||
// Show the clock box
|
||||
clock_box.style.display = 'block';
|
||||
addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
|
||||
},
|
||||
dismissClock: function(num) {
|
||||
@ -123,6 +133,7 @@ var DateTimeShortcuts = {
|
||||
today_link.appendChild(document.createTextNode(gettext('Today')));
|
||||
var cal_link = document.createElement('a');
|
||||
cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
|
||||
cal_link.id = DateTimeShortcuts.calendarLinkName + num;
|
||||
quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
|
||||
shortcuts_span.appendChild(document.createTextNode('\240'));
|
||||
shortcuts_span.appendChild(today_link);
|
||||
@ -149,18 +160,6 @@ var DateTimeShortcuts = {
|
||||
var cal_box = document.createElement('div');
|
||||
cal_box.style.display = 'none';
|
||||
cal_box.style.position = 'absolute';
|
||||
// is it left-to-right or right-to-left layout ?
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
cal_box.style.left = findPosX(cal_link) - 180 + 'px';
|
||||
}
|
||||
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
||||
cal_box.className = 'calendarbox module';
|
||||
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
||||
document.body.appendChild(cal_box);
|
||||
@ -195,7 +194,24 @@ var DateTimeShortcuts = {
|
||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
|
||||
},
|
||||
openCalendar: function(num) {
|
||||
document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'block';
|
||||
var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
|
||||
var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
|
||||
|
||||
// Recalculate the clockbox position
|
||||
// is it left-to-right or right-to-left layout ?
|
||||
if (getStyle(document.body,'direction')!='rtl') {
|
||||
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
||||
}
|
||||
else {
|
||||
// since style's width is in em, it'd be tough to calculate
|
||||
// px value of it. let's use an estimated px for now
|
||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||
// (it returns as it was left aligned), needs to be fixed.
|
||||
cal_box.style.left = findPosX(cal_link) - 180 + 'px';
|
||||
}
|
||||
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
||||
|
||||
cal_box.style.display = 'block';
|
||||
addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
|
||||
},
|
||||
dismissCalendar: function(num) {
|
||||
@ -217,7 +233,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();
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ function showRelatedObjectLookupPopup(triggeringLink) {
|
||||
} else {
|
||||
href = triggeringLink.href + '?pop=1';
|
||||
}
|
||||
var win = window.open(href, name, 'height=500,width=740,resizable=yes,scrollbars=yes');
|
||||
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||
win.focus();
|
||||
return false;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -20,30 +20,30 @@
|
||||
<div id="branding">
|
||||
{% block branding %}{% endblock %}
|
||||
</div>
|
||||
{% if not user.is_anonymous %}{% if user.is_staff %}
|
||||
{% if user.is_authenticated and user.is_staff %}
|
||||
<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
|
||||
{% endif %}{% endif %}
|
||||
{% endif %}
|
||||
{% block nav-global %}{% endblock %}
|
||||
</div>
|
||||
<!-- END Header -->
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title }}{% endif %}</div>{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title|escape }}{% endif %}</div>{% endblock %}
|
||||
{% 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 -->
|
||||
<div id="content" class="{% block coltype %}colM{% endblock %}">
|
||||
{% block pretitle %}{% endblock %}
|
||||
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
|
||||
{% block content_title %}{% if title %}<h1>{{ title|escape }}</h1>{% endif %}{% endblock %}
|
||||
{% block content %}{{ content }}{% endblock %}
|
||||
{% block sidebar %}{% endblock %}
|
||||
<br class="clear" />
|
||||
</div>
|
||||
<!-- END Content -->
|
||||
|
||||
<div id="footer"></div>
|
||||
{% block footer %}<div id="footer"></div>{% endblock %}
|
||||
</div>
|
||||
<!-- END Container -->
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{% extends "admin/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
|
||||
{% block title %}{{ title|escape }} | {% trans 'Django site admin' %}{% endblock %}
|
||||
|
||||
{% block branding %}
|
||||
<h1 id="site-name">{% trans 'Django administration' %}</h1>
|
||||
|
@ -11,8 +11,8 @@
|
||||
{% block breadcrumbs %}{% if not is_popup %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="../../../">{% trans "Home" %}</a> ›
|
||||
<a href="../">{{ opts.verbose_name_plural|capfirst }}</a> ›
|
||||
{% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
|
||||
<a href="../">{{ opts.verbose_name_plural|capfirst|escape }}</a> ›
|
||||
{% if add %}{% trans "Add" %} {{ opts.verbose_name|escape }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
|
||||
</div>
|
||||
{% endif %}{% endblock %}
|
||||
{% block content %}<div id="content-main">
|
||||
|
@ -3,12 +3,12 @@
|
||||
{% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %}
|
||||
{% block bodyclass %}change-list{% endblock %}
|
||||
{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / <a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › {{ cl.opts.verbose_name_plural|capfirst }}</div>{% endblock %}{% endif %}
|
||||
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › {{ cl.opts.verbose_name_plural|capfirst|escape }}</div>{% endblock %}{% endif %}
|
||||
{% block coltype %}flex{% endblock %}
|
||||
{% block content %}
|
||||
<div id="content-main">
|
||||
{% if has_add_permission %}
|
||||
<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
|
||||
<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
|
||||
{% endif %}
|
||||
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
|
||||
{% block search %}{% search_form cl %}{% endblock %}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{% if show %}
|
||||
<div class="xfull">
|
||||
<ul class="toplinks">
|
||||
{% if back %}<li class="date-back"><a href="{{ back.link }}">‹ {{ back.title }}</a></li>{% endif %}
|
||||
{% if back %}<li class="date-back"><a href="{{ back.link }}">‹ {{ back.title|escape }}</a></li>{% endif %}
|
||||
{% for choice in choices %}
|
||||
<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title }}{% if choice.link %}</a>{% endif %}</li>
|
||||
<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title|escape }}{% if choice.link %}</a>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul><br class="clear" />
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@ -4,21 +4,21 @@
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="../../../../">{% trans "Home" %}</a> ›
|
||||
<a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> ›
|
||||
<a href="../">{{ object|striptags|truncatewords:"18" }}</a> ›
|
||||
<a href="../../">{{ opts.verbose_name_plural|capfirst|escape }}</a> ›
|
||||
<a href="../">{{ object|escape|truncatewords:"18" }}</a> ›
|
||||
{% trans 'Delete' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% if perms_lacking %}
|
||||
<p>{% blocktrans %}Deleting the {{ object_name }} '{{ object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p>
|
||||
<p>{% blocktrans with object|escape as escaped_object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p>
|
||||
<ul>
|
||||
{% for obj in perms_lacking %}
|
||||
<li>{{ obj }}</li>
|
||||
<li>{{ obj|escape }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>{% blocktrans %}Are you sure you want to delete the {{ object_name }} "{{ object }}"? All of the following related items will be deleted:{% endblocktrans %}</p>
|
||||
<p>{% blocktrans with object|escape as escaped_object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}</p>
|
||||
<ul>{{ deleted_objects|unordered_list }}</ul>
|
||||
<form action="" method="post">
|
||||
<div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{% load admin_modify %}
|
||||
<fieldset class="module aligned">
|
||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst }} #{{ forloop.counter }}</h2>
|
||||
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst|escape }} #{{ forloop.counter }}</h2>
|
||||
{% if bound_related_object.show_url %}{% if fcw.obj.original %}
|
||||
<p><a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a></p>
|
||||
{% endif %}{% endif %}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{% load admin_modify %}
|
||||
<fieldset class="module">
|
||||
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2><table>
|
||||
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst|escape }}</h2><table>
|
||||
<thead><tr>
|
||||
{% for fw in bound_related_object.field_wrapper_list %}
|
||||
{% if fw.needs_header %}
|
||||
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst }}</th>
|
||||
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% load i18n %}
|
||||
<h3>{% blocktrans %} By {{ title }} {% endblocktrans %}</h3>
|
||||
<h3>{% blocktrans with title|escape as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3>
|
||||
<ul>
|
||||
{% for choice in choices %}
|
||||
<li{% if choice.selected %} class="selected"{% endif %}>
|
||||
|
@ -15,13 +15,13 @@
|
||||
{% 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 %}
|
||||
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
|
||||
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name|escape }}</a></th>
|
||||
{% else %}
|
||||
<th scope="row">{{ model.name }}</th>
|
||||
<th scope="row">{{ model.name|escape }}</th>
|
||||
{% endif %}
|
||||
|
||||
{% if model.perms.add %}
|
||||
@ -58,7 +58,7 @@
|
||||
{% else %}
|
||||
<ul class="actionlist">
|
||||
{% for entry in admin_log %}
|
||||
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst }}</span></li>
|
||||
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst|escape }}</span></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {{ title }}</div>{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {{ title|escape }}</div>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
@ -13,17 +13,17 @@
|
||||
{% endif %}
|
||||
<div id="content-main">
|
||||
<form action="{{ app_path }}" method="post" id="login-form">
|
||||
<div class="form-row">
|
||||
<label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
|
||||
<input type="hidden" name="this_is_the_login_form" value="1" />
|
||||
<input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %}
|
||||
</div>
|
||||
<div class="submit-row">
|
||||
<label> </label><input type="submit" value="{% trans 'Log in' %}" />
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
|
||||
<input type="hidden" name="this_is_the_login_form" value="1" />
|
||||
<input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %}
|
||||
</div>
|
||||
<div class="submit-row">
|
||||
<label> </label><input type="submit" value="{% trans 'Log in' %}" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -2,7 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> › <a href="../../">{{ module_name }}</a> › <a href="../">{{ object|truncatewords:"18" }}</a> › {% trans 'History' %}</div>
|
||||
<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> › <a href="../../">{{ module_name|escape }}</a> › <a href="../">{{ object|escape|truncatewords:"18" }}</a> › {% trans 'History' %}</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -6,6 +6,6 @@
|
||||
{% paginator_number cl i %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
|
||||
{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name|escape }}{% else %}{{ cl.opts.verbose_name_plural|escape }}{% endifequal %}
|
||||
{% if show_all_url %} <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
|
||||
</p>
|
||||
|
@ -9,17 +9,17 @@
|
||||
<h1>Documentation</h1>
|
||||
|
||||
<div id="content-main">
|
||||
<h3><a href="tags/">Tags</a></h3>
|
||||
<p>List of all the template tags and their functions.</p>
|
||||
<h3><a href="tags/">Tags</a></h3>
|
||||
<p>List of all the template tags and their functions.</p>
|
||||
|
||||
<h3><a href="filters/">Filters</a></h3>
|
||||
<p>Filters are actions which can be applied to variables in a template to alter the output.</p>
|
||||
<h3><a href="filters/">Filters</a></h3>
|
||||
<p>Filters are actions which can be applied to variables in a template to alter the output.</p>
|
||||
|
||||
<h3><a href="models/">Models</a></h3>
|
||||
<p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
|
||||
<h3><a href="models/">Models</a></h3>
|
||||
<p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
|
||||
|
||||
<h3><a href="views/">Views</a></h3>
|
||||
<p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
|
||||
<h3><a href="views/">Views</a></h3>
|
||||
<p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
|
||||
|
||||
<h3><a href="bookmarklets/">Bookmarklets</a></h3>
|
||||
<p>Tools for your browser to quickly access admin functionality.</p>
|
||||
|
@ -9,9 +9,9 @@
|
||||
<h1>Documentation</h1>
|
||||
|
||||
<div id="content-main">
|
||||
<h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3>
|
||||
<h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3>
|
||||
|
||||
<p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p>
|
||||
<p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -9,13 +9,13 @@
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Models</a> › {{ name }}</div>{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Models</a> › {{ name|escape }}</div>{% endblock %}
|
||||
|
||||
{% block title %}Model: {{ name }}{% endblock %}
|
||||
{% block title %}Model: {{ name|escape }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="content-main">
|
||||
<h1>{{ summary }}</h1>
|
||||
<h1>{{ summary|escape }}</h1>
|
||||
|
||||
{% if description %}
|
||||
<p>{% filter escape|linebreaksbr %}{% trans description %}{% endfilter %}</p>
|
||||
@ -35,7 +35,7 @@
|
||||
<tr>
|
||||
<td>{{ field.name }}</td>
|
||||
<td>{{ field.data_type }}</td>
|
||||
<td>{% if field.verbose %}{{ field.verbose }}{% endif %}{% if field.help_text %} - {{ field.help_text }}{% endif %}</td>
|
||||
<td>{% if field.verbose %}{{ field.verbose|escape }}{% endif %}{% if field.help_text %} - {{ field.help_text|escape }}{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -1,19 +1,19 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name }}</div>{% endblock %}
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name|escape }}</div>{% endblock %}
|
||||
{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||
|
||||
{% block title %}Template: {{ name }}{% endblock %}
|
||||
{% block title %}Template: {{ name|escape }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Template: "{{ name }}"</h1>
|
||||
<h1>Template: "{{ name|escape }}"</h1>
|
||||
|
||||
{% regroup templates|dictsort:"site_id" by site as templates_by_site %}
|
||||
{% for group in templates_by_site %}
|
||||
<h2>Search path for template "{{ name }}" on {{ group.grouper }}:</h2>
|
||||
<h2>Search path for template "{{ name|escape }}" on {{ group.grouper }}:</h2>
|
||||
<ol>
|
||||
{% for template in group.list|dictsort:"order" %}
|
||||
<li><code>{{ template.file }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li>
|
||||
<li><code>{{ template.file|escape }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{% endfor %}
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
<h1>{{ name }}</h1>
|
||||
|
||||
<h2 class="subhead">{{ summary }}</h2>
|
||||
<h2 class="subhead">{{ summary|escape }}</h2>
|
||||
|
||||
<p>{{ body }}</p>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% load admin_modify i18n %}{% if bound_field.original_value %}
|
||||
{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value }} </a><br />
|
||||
{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value|escape }} </a><br />
|
||||
{% trans "Change:" %}{% output_all bound_field.form_fields %}
|
||||
{% else %} {% output_all bound_field.form_fields %} {% endif %}
|
||||
|
@ -15,6 +15,6 @@
|
||||
{{ bound_field.original_value }}
|
||||
{% endif %}
|
||||
{% if bound_field.raw_id_admin %}
|
||||
{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}
|
||||
{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@ -1,2 +1,2 @@
|
||||
{% if add %}{% include "widget/foreign.html" %}{% endif %}
|
||||
{% if change %}{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}{% endif %}
|
||||
{% if change %}{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}{% endif %}
|
||||
|
@ -1,8 +1,6 @@
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, ALL_VAR
|
||||
from django.contrib.admin.views.main import ALL_VAR, EMPTY_CHANGELIST_VALUE
|
||||
from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR
|
||||
from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db import models
|
||||
from django.utils import dateformat
|
||||
@ -119,7 +117,7 @@ def items_for_result(cl, result):
|
||||
if callable(attr):
|
||||
attr = attr()
|
||||
result_repr = str(attr)
|
||||
except AttributeError, ObjectDoesNotExist:
|
||||
except (AttributeError, ObjectDoesNotExist):
|
||||
result_repr = EMPTY_CHANGELIST_VALUE
|
||||
else:
|
||||
# Strip HTML tags in the resulting text, except if the
|
||||
@ -165,12 +163,14 @@ def items_for_result(cl, result):
|
||||
result_repr = escape(str(field_val))
|
||||
if result_repr == '':
|
||||
result_repr = ' '
|
||||
if first: # First column is a special case
|
||||
# If list_display_links not defined, add the link tag to the first field
|
||||
if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links:
|
||||
table_tag = {True:'th', False:'td'}[first]
|
||||
first = False
|
||||
url = cl.url_for_result(result)
|
||||
result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints)
|
||||
yield ('<th%s><a href="%s"%s>%s</a></th>' % \
|
||||
(row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr))
|
||||
yield ('<%s%s><a href="%s"%s>%s</a></%s>' % \
|
||||
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag))
|
||||
else:
|
||||
yield ('<td%s>%s</td>' % (row_class, result_repr))
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
from django import template
|
||||
from django.contrib.admin.views.main import AdminBoundField
|
||||
from django.template import loader
|
||||
from django.utils.html import escape
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.functional import curry
|
||||
from django.db import models
|
||||
from django.db.models.fields import Field
|
||||
from django.db.models.related import BoundRelatedObject
|
||||
|
@ -1,9 +1,15 @@
|
||||
from django.conf import settings
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
if settings.USE_I18N:
|
||||
i18n_view = 'django.views.i18n.javascript_catalog'
|
||||
else:
|
||||
i18n_view = 'django.views.i18n.null_javascript_catalog'
|
||||
|
||||
urlpatterns = patterns('',
|
||||
('^$', 'django.contrib.admin.views.main.index'),
|
||||
('^r/(\d+)/(.*)/$', 'django.views.defaults.shortcut'),
|
||||
('^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': 'django.conf'}),
|
||||
('^jsi18n/$', i18n_view, {'packages': 'django.conf'}),
|
||||
('^logout/$', 'django.contrib.auth.views.logout'),
|
||||
('^password_change/$', 'django.contrib.auth.views.password_change'),
|
||||
('^password_change/done/$', 'django.contrib.auth.views.password_change_done'),
|
||||
@ -29,3 +35,5 @@ urlpatterns = patterns('',
|
||||
('^([^/]+)/([^/]+)/(.+)/delete/$', 'django.contrib.admin.views.main.delete_stage'),
|
||||
('^([^/]+)/([^/]+)/(.+)/$', 'django.contrib.admin.views.main.change_stage'),
|
||||
)
|
||||
|
||||
del i18n_view
|
||||
|
@ -3,7 +3,6 @@
|
||||
import re
|
||||
from email.Parser import HeaderParser
|
||||
from email.Errors import HeaderParseError
|
||||
from urlparse import urljoin
|
||||
try:
|
||||
import docutils.core
|
||||
import docutils.nodes
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django import http, template
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User, SESSION_KEY
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth import authenticate, login
|
||||
from django.shortcuts import render_to_response
|
||||
from django.utils.translation import gettext_lazy
|
||||
import base64, datetime, md5
|
||||
@ -45,7 +46,7 @@ def staff_member_required(view_func):
|
||||
member, displaying the login page if necessary.
|
||||
"""
|
||||
def _checklogin(request, *args, **kwargs):
|
||||
if not request.user.is_anonymous() and request.user.is_staff:
|
||||
if request.user.is_authenticated() and request.user.is_staff:
|
||||
# The user is valid. Continue to the admin page.
|
||||
if request.POST.has_key('post_data'):
|
||||
# User must have re-authenticated through a different window
|
||||
@ -69,10 +70,10 @@ def staff_member_required(view_func):
|
||||
return _display_login_form(request, message)
|
||||
|
||||
# Check the password.
|
||||
username = request.POST.get('username', '')
|
||||
try:
|
||||
user = User.objects.get(username=username, is_staff=True)
|
||||
except User.DoesNotExist:
|
||||
username = request.POST.get('username', None)
|
||||
password = request.POST.get('password', None)
|
||||
user = authenticate(username=username, password=password)
|
||||
if user is None:
|
||||
message = ERROR_MESSAGE
|
||||
if '@' in username:
|
||||
# Mistakenly entered e-mail address instead of username? Look it up.
|
||||
@ -86,8 +87,9 @@ def staff_member_required(view_func):
|
||||
|
||||
# The user data is correct; log in the user in and continue.
|
||||
else:
|
||||
if user.check_password(request.POST.get('password', '')):
|
||||
request.session[SESSION_KEY] = user.id
|
||||
if user.is_staff:
|
||||
login(request, user)
|
||||
# TODO: set last_login with an event.
|
||||
user.last_login = datetime.datetime.now()
|
||||
user.save()
|
||||
if request.POST.has_key('post_data'):
|
||||
|
@ -14,6 +14,10 @@ import inspect, os, re
|
||||
# Exclude methods starting with these strings from documentation
|
||||
MODEL_METHODS_EXCLUDE = ('_', 'add_', 'delete', 'save', 'set_')
|
||||
|
||||
class GenericSite(object):
|
||||
domain = 'example.com'
|
||||
name = 'my site'
|
||||
|
||||
def doc_index(request):
|
||||
if not utils.docutils_is_available:
|
||||
return missing_docutils_page(request)
|
||||
@ -24,7 +28,7 @@ def bookmarklets(request):
|
||||
# Hack! This couples this view to the URL it lives at.
|
||||
admin_root = request.path[:-len('doc/bookmarklets/')]
|
||||
return render_to_response('admin_doc/bookmarklets.html', {
|
||||
'admin_url': "%s://%s%s" % (os.environ.get('HTTPS') == 'on' and 'https' or 'http', get_host(request), admin_root),
|
||||
'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', get_host(request), admin_root),
|
||||
}, context_instance=RequestContext(request))
|
||||
bookmarklets = staff_member_required(bookmarklets)
|
||||
|
||||
@ -102,12 +106,16 @@ def view_index(request):
|
||||
for settings_mod in settings_modules:
|
||||
urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', [''])
|
||||
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
|
||||
if Site._meta.installed:
|
||||
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
|
||||
else:
|
||||
site_obj = GenericSite()
|
||||
for (func, regex) in view_functions:
|
||||
views.append({
|
||||
'name': func.__name__,
|
||||
'module': func.__module__,
|
||||
'site_id': settings_mod.SITE_ID,
|
||||
'site': Site.objects.get(pk=settings_mod.SITE_ID),
|
||||
'site': site_obj,
|
||||
'url': simplify_regex(regex),
|
||||
})
|
||||
return render_to_response('admin_doc/view_index.html', {'views': views}, context_instance=RequestContext(request))
|
||||
@ -180,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.
|
||||
@ -228,6 +236,10 @@ def template_detail(request, template):
|
||||
templates = []
|
||||
for site_settings_module in settings.ADMIN_FOR:
|
||||
settings_mod = __import__(site_settings_module, '', '', [''])
|
||||
if Site._meta.installed:
|
||||
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
|
||||
else:
|
||||
site_obj = GenericSite()
|
||||
for dir in settings_mod.TEMPLATE_DIRS:
|
||||
template_file = os.path.join(dir, "%s.html" % template)
|
||||
templates.append({
|
||||
@ -235,7 +247,7 @@ def template_detail(request, template):
|
||||
'exists': os.path.exists(template_file),
|
||||
'contents': lambda: os.path.exists(template_file) and open(template_file).read() or '',
|
||||
'site_id': settings_mod.SITE_ID,
|
||||
'site': Site.objects.get(pk=settings_mod.SITE_ID),
|
||||
'site': site_obj,
|
||||
'order': list(settings_mod.TEMPLATE_DIRS).index(dir),
|
||||
})
|
||||
return render_to_response('admin_doc/template_detail.html', {
|
||||
|
@ -10,9 +10,6 @@ from django.shortcuts import get_object_or_404, render_to_response
|
||||
from django.db import models
|
||||
from django.db.models.query import handle_legacy_orderlist, QuerySet
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.template import loader
|
||||
from django.utils import dateformat
|
||||
from django.utils.dates import MONTHS
|
||||
from django.utils.html import escape
|
||||
from django.utils.text import capfirst, get_text_list
|
||||
import operator
|
||||
|
@ -22,7 +22,7 @@ def template_validator(request):
|
||||
new_data = request.POST.copy()
|
||||
errors = manipulator.get_validation_errors(new_data)
|
||||
if not errors:
|
||||
request.user.add_message('The template is valid.')
|
||||
request.user.message_set.create(message='The template is valid.')
|
||||
return render_to_response('admin/template_validator.html', {
|
||||
'title': 'Template validator',
|
||||
'form': forms.FormWrapper(manipulator, new_data, errors),
|
||||
@ -32,7 +32,7 @@ template_validator = staff_member_required(template_validator)
|
||||
class TemplateValidator(forms.Manipulator):
|
||||
def __init__(self, settings_modules):
|
||||
self.settings_modules = settings_modules
|
||||
site_list = Site.objects.get_in_bulk(settings_modules.keys()).values()
|
||||
site_list = Site.objects.in_bulk(settings_modules.keys()).values()
|
||||
self.fields = (
|
||||
forms.SelectField('site', is_required=True, choices=[(s.id, s.name) for s in site_list]),
|
||||
forms.LargeTextField('template', is_required=True, rows=25, validator_list=[self.isValidTemplate]),
|
||||
|
@ -1,29 +1,77 @@
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
SESSION_KEY = '_auth_user_id'
|
||||
BACKEND_SESSION_KEY = '_auth_user_backend'
|
||||
LOGIN_URL = '/accounts/login/'
|
||||
REDIRECT_FIELD_NAME = 'next'
|
||||
|
||||
class NoMatchFound(Exception): pass
|
||||
def load_backend(path):
|
||||
i = path.rfind('.')
|
||||
module, attr = path[:i], path[i+1:]
|
||||
try:
|
||||
mod = __import__(module, '', '', [attr])
|
||||
except ImportError, e:
|
||||
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
|
||||
try:
|
||||
cls = getattr(mod, attr)
|
||||
except AttributeError:
|
||||
raise ImproperlyConfigured, 'Module "%s" does not define a "%s" authentication backend' % (module, attr)
|
||||
return cls()
|
||||
|
||||
class HasPermission(object):
|
||||
def get_backends():
|
||||
from django.conf import settings
|
||||
backends = []
|
||||
for backend_path in settings.AUTHENTICATION_BACKENDS:
|
||||
backends.append(load_backend(backend_path))
|
||||
return backends
|
||||
|
||||
def authenticate(**credentials):
|
||||
"""
|
||||
Function that supports multiple implementations via a type registry. The
|
||||
implemetation called depends on the argument types.
|
||||
If the given credentials are valid, return a User object.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.registry = {}
|
||||
for backend in get_backends():
|
||||
try:
|
||||
user = backend.authenticate(**credentials)
|
||||
except TypeError:
|
||||
# This backend doesn't accept these credentials as arguments. Try the next one.
|
||||
continue
|
||||
if user is None:
|
||||
continue
|
||||
# Annotate the user object with the path of the backend.
|
||||
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
|
||||
return user
|
||||
|
||||
def __call__(self, user, permission, obj=None):
|
||||
# TODO: this isn't very robust. Only matches on exact types. Support
|
||||
# for matching subclasses and caching registry hits would be helpful,
|
||||
# but we'll add that later
|
||||
types = (type(user), type(permission), type(obj))
|
||||
func = self.registry.get(types)
|
||||
if func is not None:
|
||||
return func(user, permission, obj)
|
||||
else:
|
||||
raise NoMatchFound, "%s\n%s" % (self.registry, types)
|
||||
def login(request, user):
|
||||
"""
|
||||
Persist a user id and a backend in the request. This way a user doesn't
|
||||
have to reauthenticate on every request.
|
||||
"""
|
||||
if user is None:
|
||||
user = request.user
|
||||
# TODO: It would be nice to support different login methods, like signed cookies.
|
||||
request.session[SESSION_KEY] = user.id
|
||||
request.session[BACKEND_SESSION_KEY] = user.backend
|
||||
|
||||
def register(self, user_type, permission_type, obj_type, func):
|
||||
types = (user_type, permission_type, obj_type)
|
||||
self.registry[types] = func
|
||||
def logout(request):
|
||||
"""
|
||||
Remove the authenticated user's ID from the request.
|
||||
"""
|
||||
try:
|
||||
del request.session[SESSION_KEY]
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
del request.session[BACKEND_SESSION_KEY]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
has_permission = HasPermission()
|
||||
def get_user(request):
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
try:
|
||||
user_id = request.session[SESSION_KEY]
|
||||
backend_path = request.session[BACKEND_SESSION_KEY]
|
||||
backend = load_backend(backend_path)
|
||||
user = backend.get_user(user_id) or AnonymousUser()
|
||||
except KeyError:
|
||||
user = AnonymousUser()
|
||||
return user
|
||||
|
21
django/contrib/auth/backends.py
Normal file
21
django/contrib/auth/backends.py
Normal file
@ -0,0 +1,21 @@
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class ModelBackend:
|
||||
"""
|
||||
Authenticate against django.contrib.auth.models.User
|
||||
"""
|
||||
# TODO: Model, login attribute name and password attribute name should be
|
||||
# configurable.
|
||||
def authenticate(self, username=None, password=None):
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
if user.check_password(password):
|
||||
return user
|
||||
except User.DoesNotExist:
|
||||
return None
|
||||
|
||||
def get_user(self, user_id):
|
||||
try:
|
||||
return User.objects.get(pk=user_id)
|
||||
except User.DoesNotExist:
|
||||
return None
|
@ -13,11 +13,13 @@ def user_passes_test(test_func, login_url=LOGIN_URL):
|
||||
if test_func(request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
|
||||
_checklogin.__doc__ = view_func.__doc__
|
||||
_checklogin.__dict__ = view_func.__dict__
|
||||
|
||||
return _checklogin
|
||||
return _dec
|
||||
|
||||
login_required = user_passes_test(lambda u: not u.is_anonymous())
|
||||
login_required = user_passes_test(lambda u: u.is_authenticated())
|
||||
login_required.__doc__ = (
|
||||
"""
|
||||
Decorator for views that checks that the user is logged in, redirecting
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth import authenticate
|
||||
from django.contrib.sites.models import Site
|
||||
from django.template import Context, loader
|
||||
from django.core import validators
|
||||
@ -20,8 +21,7 @@ class AuthenticationForm(forms.Manipulator):
|
||||
self.fields = [
|
||||
forms.TextField(field_name="username", length=15, maxlength=30, is_required=True,
|
||||
validator_list=[self.isValidUser, self.hasCookiesEnabled]),
|
||||
forms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True,
|
||||
validator_list=[self.isValidPasswordForUser]),
|
||||
forms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True),
|
||||
]
|
||||
self.user_cache = None
|
||||
|
||||
@ -30,16 +30,10 @@ class AuthenticationForm(forms.Manipulator):
|
||||
raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.")
|
||||
|
||||
def isValidUser(self, field_data, all_data):
|
||||
try:
|
||||
self.user_cache = User.objects.get(username=field_data)
|
||||
except User.DoesNotExist:
|
||||
raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||
|
||||
def isValidPasswordForUser(self, field_data, all_data):
|
||||
username = field_data
|
||||
password = all_data.get('password', None)
|
||||
self.user_cache = authenticate(username=username, password=password)
|
||||
if self.user_cache is None:
|
||||
return
|
||||
if not self.user_cache.check_password(field_data):
|
||||
self.user_cache = None
|
||||
raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||
elif not self.user_cache.is_active:
|
||||
raise validators.ValidationError, _("This account is inactive.")
|
||||
@ -67,7 +61,7 @@ class PasswordResetForm(forms.Manipulator):
|
||||
except User.DoesNotExist:
|
||||
raise validators.ValidationError, "That e-mail address doesn't have an associated user acount. Are you sure you've registered?"
|
||||
|
||||
def save(self, domain_override=None):
|
||||
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
|
||||
"Calculates a new password randomly and sends it to the user"
|
||||
from django.core.mail import send_mail
|
||||
new_pass = User.objects.make_random_password()
|
||||
@ -79,7 +73,7 @@ class PasswordResetForm(forms.Manipulator):
|
||||
domain = current_site.domain
|
||||
else:
|
||||
site_name = domain = domain_override
|
||||
t = loader.get_template('registration/password_reset_email.html')
|
||||
t = loader.get_template(email_template_name)
|
||||
c = {
|
||||
'new_password': new_pass,
|
||||
'email': self.user_cache.email,
|
||||
|
@ -4,12 +4,8 @@ class LazyUser(object):
|
||||
|
||||
def __get__(self, request, obj_type=None):
|
||||
if self._user is None:
|
||||
from django.contrib.auth.models import User, AnonymousUser, SESSION_KEY
|
||||
try:
|
||||
user_id = request.session[SESSION_KEY]
|
||||
self._user = User.objects.get(pk=user_id)
|
||||
except (KeyError, User.DoesNotExist):
|
||||
self._user = AnonymousUser()
|
||||
from django.contrib.auth import get_user
|
||||
self._user = get_user(request)
|
||||
return self._user
|
||||
|
||||
class AuthenticationMiddleware(object):
|
||||
|
@ -1,10 +1,23 @@
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import backend, connection, models
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import datetime
|
||||
|
||||
SESSION_KEY = '_auth_user_id'
|
||||
def check_password(raw_password, enc_password):
|
||||
"""
|
||||
Returns a boolean of whether the raw_password was correct. Handles
|
||||
encryption formats behind the scenes.
|
||||
"""
|
||||
algo, salt, hsh = enc_password.split('$')
|
||||
if algo == 'md5':
|
||||
import md5
|
||||
return hsh == md5.new(salt+raw_password).hexdigest()
|
||||
elif algo == 'sha1':
|
||||
import sha
|
||||
return hsh == sha.new(salt+raw_password).hexdigest()
|
||||
raise ValueError, "Got unknown password algorithm type in password."
|
||||
|
||||
class SiteProfileNotAvailable(Exception):
|
||||
pass
|
||||
@ -113,6 +126,11 @@ class User(models.Model):
|
||||
def is_anonymous(self):
|
||||
"Always returns False. This is a way of comparing User objects to anonymous users."
|
||||
return False
|
||||
|
||||
def is_authenticated(self):
|
||||
"""Always return True. This is a way to tell if the user has been authenticated in templates.
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_full_name(self):
|
||||
"Returns the first_name plus the last_name, with a space in between."
|
||||
@ -141,14 +159,7 @@ class User(models.Model):
|
||||
self.set_password(raw_password)
|
||||
self.save()
|
||||
return is_correct
|
||||
algo, salt, hsh = self.password.split('$')
|
||||
if algo == 'md5':
|
||||
import md5
|
||||
return hsh == md5.new(salt+raw_password).hexdigest()
|
||||
elif algo == 'sha1':
|
||||
import sha
|
||||
return hsh == sha.new(salt+raw_password).hexdigest()
|
||||
raise ValueError, "Got unknown password algorithm type in password."
|
||||
return check_password(raw_password, self.password)
|
||||
|
||||
def get_group_permissions(self):
|
||||
"Returns a list of permission strings that this user has through his/her groups."
|
||||
@ -234,7 +245,7 @@ class User(models.Model):
|
||||
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
|
||||
model = models.get_model(app_label, model_name)
|
||||
self._profile_cache = model._default_manager.get(user__id__exact=self.id)
|
||||
except ImportError, ImproperlyConfigured:
|
||||
except (ImportError, ImproperlyConfigured):
|
||||
raise SiteProfileNotAvailable
|
||||
return self._profile_cache
|
||||
|
||||
@ -288,3 +299,6 @@ class AnonymousUser(object):
|
||||
|
||||
def is_anonymous(self):
|
||||
return True
|
||||
|
||||
def is_authenticated(self):
|
||||
return False
|
||||
|
@ -3,9 +3,8 @@ from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm
|
||||
from django import forms
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.contrib.auth.models import SESSION_KEY
|
||||
from django.contrib.sites.models import Site
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
|
||||
|
||||
@ -19,7 +18,8 @@ def login(request, template_name='registration/login.html'):
|
||||
# Light security check -- make sure redirect_to isn't garbage.
|
||||
if not redirect_to or '://' in redirect_to or ' ' in redirect_to:
|
||||
redirect_to = '/accounts/profile/'
|
||||
request.session[SESSION_KEY] = manipulator.get_user_id()
|
||||
from django.contrib.auth import login
|
||||
login(request, manipulator.get_user())
|
||||
request.session.delete_test_cookie()
|
||||
return HttpResponseRedirect(redirect_to)
|
||||
else:
|
||||
@ -33,9 +33,9 @@ def login(request, template_name='registration/login.html'):
|
||||
|
||||
def logout(request, next_page=None, template_name='registration/logged_out.html'):
|
||||
"Logs out the user and displays 'You are logged out' message."
|
||||
try:
|
||||
del request.session[SESSION_KEY]
|
||||
except KeyError:
|
||||
from django.contrib.auth import logout
|
||||
logout(request)
|
||||
if next_page is None:
|
||||
return render_to_response(template_name, {'title': _('Logged out')}, context_instance=RequestContext(request))
|
||||
else:
|
||||
# Redirect to this page until the session has been cleared.
|
||||
@ -49,7 +49,8 @@ def redirect_to_login(next, login_url=LOGIN_URL):
|
||||
"Redirects the user to the login page, passing the given 'next' page"
|
||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
|
||||
|
||||
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html'):
|
||||
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
|
||||
email_template_name='registration/password_reset_email.html'):
|
||||
new_data, errors = {}, {}
|
||||
form = PasswordResetForm()
|
||||
if request.POST:
|
||||
@ -57,9 +58,9 @@ def password_reset(request, is_admin_site=False, template_name='registration/pas
|
||||
errors = form.get_validation_errors(new_data)
|
||||
if not errors:
|
||||
if is_admin_site:
|
||||
form.save(request.META['HTTP_HOST'])
|
||||
form.save(domain_override=request.META['HTTP_HOST'])
|
||||
else:
|
||||
form.save()
|
||||
form.save(email_template_name=email_template_name)
|
||||
return HttpResponseRedirect('%sdone/' % request.path)
|
||||
return render_to_response(template_name, {'form': forms.FormWrapper(form, new_data, errors)},
|
||||
context_instance=RequestContext(request))
|
||||
|
@ -1,7 +1,6 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.comments.models import Comment, FreeComment
|
||||
from django.contrib.syndication.feeds import Feed
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
class LatestFreeCommentsFeed(Feed):
|
||||
@ -37,6 +36,6 @@ class LatestCommentsFeed(LatestFreeCommentsFeed):
|
||||
qs = qs.filter(is_removed=False)
|
||||
if settings.COMMENTS_BANNED_USERS_GROUP:
|
||||
where = ['user_id NOT IN (SELECT user_id FROM auth_users_group WHERE group_id = %s)']
|
||||
params = [COMMENTS_BANNED_USERS_GROUP]
|
||||
params = [settings.COMMENTS_BANNED_USERS_GROUP]
|
||||
qs = qs.extra(where=where, params=params)
|
||||
return qs
|
||||
|
@ -51,7 +51,7 @@ class CommentManager(models.Manager):
|
||||
extra_kwargs.setdefault('select', {})
|
||||
extra_kwargs['select']['_karma_total_good'] = 'SELECT COUNT(*) FROM comments_karmascore, comments_comment WHERE comments_karmascore.comment_id=comments_comment.id AND score=1'
|
||||
extra_kwargs['select']['_karma_total_bad'] = 'SELECT COUNT(*) FROM comments_karmascore, comments_comment WHERE comments_karmascore.comment_id=comments_comment.id AND score=-1'
|
||||
return self.filter(**kwargs).extra(**extra_kwargs)
|
||||
return self.filter(**kwargs).extra(**extra_kwargs)
|
||||
|
||||
def user_is_moderator(self, user):
|
||||
if user.is_superuser:
|
||||
|
@ -2,10 +2,10 @@
|
||||
{% if display_form %}
|
||||
<form {% if photos_optional or photos_required %}enctype="multipart/form-data" {% endif %}action="/comments/post/" method="post">
|
||||
|
||||
{% if user.is_anonymous %}
|
||||
<p>{% trans "Username:" %} <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p>
|
||||
{% else %}
|
||||
{% if user.is_authenticated %}
|
||||
<p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="/accounts/logout/">{% trans "Log out" %}</a>)</p>
|
||||
{% else %}
|
||||
<p><label for="id_username">{% trans "Username:" %}</label> <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p>
|
||||
{% endif %}
|
||||
|
||||
{% if ratings_optional or ratings_required %}
|
||||
@ -20,15 +20,19 @@
|
||||
{% endif %}
|
||||
|
||||
{% if photos_optional or photos_required %}
|
||||
<p>{% trans "Post a photo" %} ({% if photos_required %}{% trans "Required" %}{% else %}{% trans "Optional" %}{% endif %}): <input type="file" name="photo" /></p>
|
||||
<p><label for="id_photo">{% trans "Post a photo" %}</label> ({% if photos_required %}{% trans "Required" %}{% else %}{% trans "Optional" %}{% endif %}):
|
||||
<input type="file" name="photo" id="id_photo" /></p>
|
||||
<input type="hidden" name="photo_options" value="{{ photo_options }}" />
|
||||
{% endif %}
|
||||
|
||||
<p>{% trans "Comment:" %}<br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></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 %}
|
||||
|
@ -1,11 +1,13 @@
|
||||
{% load i18n %}
|
||||
{% if display_form %}
|
||||
<form action="/comments/postfree/" method="post">
|
||||
<p>{% trans "Your name:" %} <input type="text" id="id_person_name" name="person_name" /></p>
|
||||
<p>{% trans "Comment:" %}<br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p>
|
||||
<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 %}
|
||||
|
@ -114,7 +114,7 @@ class CommentListNode(template.Node):
|
||||
comment_list = get_list_function(**kwargs).order_by(self.ordering + 'submit_date').select_related()
|
||||
|
||||
if not self.free:
|
||||
if context.has_key('user') and not context['user'].is_anonymous():
|
||||
if context.has_key('user') and context['user'].is_authenticated():
|
||||
user_id = context['user'].id
|
||||
context['user_can_moderate_comments'] = Comment.objects.user_is_moderator(context['user'])
|
||||
else:
|
||||
|
@ -5,8 +5,7 @@ from django.http import Http404
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.contrib.auth.models import SESSION_KEY
|
||||
from django.contrib.comments.models import Comment, FreeComment, PHOTOS_REQUIRED, PHOTOS_OPTIONAL, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC
|
||||
from django.contrib.comments.models import Comment, FreeComment, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.http import HttpResponseRedirect
|
||||
@ -64,7 +63,7 @@ class PublicCommentManipulator(AuthenticationForm):
|
||||
validator_list=get_validator_list(8),
|
||||
),
|
||||
])
|
||||
if not user.is_anonymous():
|
||||
if user.is_authenticated():
|
||||
self["username"].is_required = False
|
||||
self["username"].validator_list = []
|
||||
self["password"].is_required = False
|
||||
@ -219,7 +218,8 @@ def post_comment(request):
|
||||
# If user gave correct username/password and wasn't already logged in, log them in
|
||||
# so they don't have to enter a username/password again.
|
||||
if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
|
||||
request.session[SESSION_KEY] = manipulator.get_user_id()
|
||||
from django.contrib.auth import login
|
||||
login(request, manipulator.get_user())
|
||||
if errors or request.POST.has_key('preview'):
|
||||
class CommentFormWrapper(forms.FormWrapper):
|
||||
def __init__(self, manipulator, new_data, errors, rating_choices):
|
||||
|
@ -15,7 +15,7 @@ def vote(request, comment_id, vote):
|
||||
rating = {'up': 1, 'down': -1}.get(vote, False)
|
||||
if not rating:
|
||||
raise Http404, "Invalid vote"
|
||||
if request.user.is_anonymous():
|
||||
if not request.user.is_authenticated():
|
||||
raise Http404, _("Anonymous users cannot vote")
|
||||
try:
|
||||
comment = Comment.objects.get(pk=comment_id)
|
||||
|
@ -10,7 +10,7 @@ class FlatPage(models.Model):
|
||||
content = models.TextField(_('content'))
|
||||
enable_comments = models.BooleanField(_('enable comments'))
|
||||
template_name = models.CharField(_('template name'), maxlength=70, blank=True,
|
||||
help_text=_("Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."))
|
||||
help_text=_("Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'."))
|
||||
registration_required = models.BooleanField(_('registration required'), help_text=_("If this is checked, only logged-in users will be able to view the page."))
|
||||
sites = models.ManyToManyField(Site)
|
||||
class Meta:
|
||||
|
@ -22,7 +22,7 @@ def flatpage(request, url):
|
||||
f = get_object_or_404(FlatPage, url__exact=url, sites__id__exact=settings.SITE_ID)
|
||||
# If registration is required for accessing this page, and the user isn't
|
||||
# logged in, redirect to the login page.
|
||||
if f.registration_required and request.user.is_anonymous():
|
||||
if f.registration_required and not request.user.is_authenticated():
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
return redirect_to_login(request.path)
|
||||
if f.template_name:
|
||||
|
@ -27,7 +27,7 @@ def textile(value):
|
||||
raise template.TemplateSyntaxError, "Error in {% textile %} filter: The Python textile library isn't installed."
|
||||
return value
|
||||
else:
|
||||
return textile.textile(value)
|
||||
return textile.textile(value, encoding=settings.DEFAULT_CHARSET, output=settings.DEFAULT_CHARSET)
|
||||
|
||||
def markdown(value):
|
||||
try:
|
||||
@ -47,7 +47,8 @@ def restructuredtext(value):
|
||||
raise template.TemplateSyntaxError, "Error in {% restructuredtext %} filter: The Python docutils library isn't installed."
|
||||
return value
|
||||
else:
|
||||
parts = publish_parts(source=value, writer_name="html4css1")
|
||||
docutils_settings = getattr(settings, "RESTRUCTUREDTEXT_FILTER_SETTINGS", {})
|
||||
parts = publish_parts(source=value, writer_name="html4css1", settings_overrides=docutils_settings)
|
||||
return parts["fragment"]
|
||||
|
||||
register.filter(textile)
|
||||
|
@ -32,11 +32,21 @@ class SessionManager(models.Manager):
|
||||
return s
|
||||
|
||||
class Session(models.Model):
|
||||
"""Django provides full support for anonymous sessions. The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis. It stores data on the server side and abstracts the sending and receiving of cookies. Cookies contain a session ID -- not the data itself.
|
||||
"""
|
||||
Django provides full support for anonymous sessions. The session
|
||||
framework lets you store and retrieve arbitrary data on a
|
||||
per-site-visitor basis. It stores data on the server side and
|
||||
abstracts the sending and receiving of cookies. Cookies contain a
|
||||
session ID -- not the data itself.
|
||||
|
||||
The Django sessions framework is entirely cookie-based. It does not fall back to putting session IDs in URLs. This is an intentional design decision. Not only does that behavior make URLs ugly, it makes your site vulnerable to session-ID theft via the "Referer" header.
|
||||
The Django sessions framework is entirely cookie-based. It does
|
||||
not fall back to putting session IDs in URLs. This is an intentional
|
||||
design decision. Not only does that behavior make URLs ugly, it makes
|
||||
your site vulnerable to session-ID theft via the "Referer" header.
|
||||
|
||||
For complete documentation on using Sessions in your code, consult the sessions documentation that is shipped with Django (also available on the Django website).
|
||||
For complete documentation on using Sessions in your code, consult
|
||||
the sessions documentation that is shipped with Django (also available
|
||||
on the Django website).
|
||||
"""
|
||||
session_key = models.CharField(_('session key'), maxlength=40, primary_key=True)
|
||||
session_data = models.TextField(_('session data'))
|
||||
|
@ -16,10 +16,14 @@ class Feed(object):
|
||||
item_pubdate = None
|
||||
item_enclosure_url = None
|
||||
feed_type = feedgenerator.DefaultFeed
|
||||
title_template = None
|
||||
description_template = None
|
||||
|
||||
def __init__(self, slug, feed_url):
|
||||
self.slug = slug
|
||||
self.feed_url = feed_url
|
||||
self.title_template_name = self.title_template or ('feeds/%s_title.html' % slug)
|
||||
self.description_template_name = self.description_template or ('feeds/%s_description.html' % slug)
|
||||
|
||||
def item_link(self, item):
|
||||
try:
|
||||
@ -69,7 +73,7 @@ class Feed(object):
|
||||
link = link,
|
||||
description = self.__get_dynamic_attr('description', obj),
|
||||
language = settings.LANGUAGE_CODE.decode(),
|
||||
feed_url = add_domain(current_site, self.feed_url),
|
||||
feed_url = add_domain(current_site, self.__get_dynamic_attr('feed_url', obj)),
|
||||
author_name = self.__get_dynamic_attr('author_name', obj),
|
||||
author_link = self.__get_dynamic_attr('author_link', obj),
|
||||
author_email = self.__get_dynamic_attr('author_email', obj),
|
||||
@ -77,13 +81,13 @@ class Feed(object):
|
||||
)
|
||||
|
||||
try:
|
||||
title_template = loader.get_template('feeds/%s_title.html' % self.slug)
|
||||
title_tmp = loader.get_template(self.title_template_name)
|
||||
except TemplateDoesNotExist:
|
||||
title_template = Template('{{ obj }}')
|
||||
title_tmp = Template('{{ obj }}')
|
||||
try:
|
||||
description_template = loader.get_template('feeds/%s_description.html' % self.slug)
|
||||
description_tmp = loader.get_template(self.description_template_name)
|
||||
except TemplateDoesNotExist:
|
||||
description_template = Template('{{ obj }}')
|
||||
description_tmp = Template('{{ obj }}')
|
||||
|
||||
for item in self.__get_dynamic_attr('items', obj):
|
||||
link = add_domain(current_site.domain, self.__get_dynamic_attr('item_link', item))
|
||||
@ -102,9 +106,9 @@ class Feed(object):
|
||||
else:
|
||||
author_email = author_link = None
|
||||
feed.add_item(
|
||||
title = title_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'),
|
||||
title = title_tmp.render(Context({'obj': item, 'site': current_site})).decode('utf-8'),
|
||||
link = link,
|
||||
description = description_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'),
|
||||
description = description_tmp.render(Context({'obj': item, 'site': current_site})).decode('utf-8'),
|
||||
unique_id = link,
|
||||
enclosure = enc,
|
||||
pubdate = self.__get_dynamic_attr('item_pubdate', item),
|
||||
|
2
django/core/cache/backends/db.py
vendored
2
django/core/cache/backends/db.py
vendored
@ -1,7 +1,7 @@
|
||||
"Database cache backend."
|
||||
|
||||
from django.core.cache.backends.base import BaseCache
|
||||
from django.db import connection, transaction
|
||||
from django.db import connection, transaction, DatabaseError
|
||||
import base64, time
|
||||
from datetime import datetime
|
||||
try:
|
||||
|
4
django/core/cache/backends/locmem.py
vendored
4
django/core/cache/backends/locmem.py
vendored
@ -3,10 +3,6 @@
|
||||
from django.core.cache.backends.simple import CacheClass as SimpleCacheClass
|
||||
from django.utils.synch import RWLock
|
||||
import copy, time
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
|
||||
class CacheClass(SimpleCacheClass):
|
||||
def __init__(self, host, params):
|
||||
|
@ -119,7 +119,6 @@ class BaseHandler(object):
|
||||
Returns an HttpResponse that displays a PUBLIC error message for a
|
||||
fundamental error.
|
||||
"""
|
||||
from django.core import urlresolvers
|
||||
callback, param_dict = resolver.resolve500()
|
||||
return callback(request, **param_dict)
|
||||
|
||||
|
@ -23,6 +23,9 @@ class ModPythonRequest(http.HttpRequest):
|
||||
def get_full_path(self):
|
||||
return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
|
||||
|
||||
def is_secure(self):
|
||||
return self._req.subprocess_env.has_key('HTTPS') and self._req.subprocess_env['HTTPS'] == 'on'
|
||||
|
||||
def _load_post_and_files(self):
|
||||
"Populates self._post and self._files"
|
||||
if self._req.headers_in.has_key('content-type') and self._req.headers_in['content-type'].startswith('multipart'):
|
||||
@ -145,7 +148,6 @@ class ModPythonHandler(BaseHandler):
|
||||
|
||||
def populate_apache_request(http_response, mod_python_req):
|
||||
"Populates the mod_python request object with an HttpResponse"
|
||||
from django.conf import settings
|
||||
mod_python_req.content_type = http_response['Content-Type']
|
||||
for key, value in http_response.headers.items():
|
||||
if key != 'Content-Type':
|
||||
|
@ -54,18 +54,20 @@ class WSGIRequest(http.HttpRequest):
|
||||
def __init__(self, environ):
|
||||
self.environ = environ
|
||||
self.path = environ['PATH_INFO']
|
||||
self.META = environ
|
||||
self.META = environ
|
||||
self.method = environ['REQUEST_METHOD'].upper()
|
||||
|
||||
def __repr__(self):
|
||||
from pprint import pformat
|
||||
return '<DjangoRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
|
||||
return '<WSGIRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
|
||||
(pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
|
||||
pformat(self.META))
|
||||
|
||||
def get_full_path(self):
|
||||
return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')
|
||||
|
||||
def is_secure(self):
|
||||
return self.environ.has_key('HTTPS') and self.environ['HTTPS'] == 'on'
|
||||
|
||||
def _load_post_and_files(self):
|
||||
# Populates self._post and self._files
|
||||
if self.method == 'POST':
|
||||
|
@ -45,8 +45,8 @@ def disable_termcolors():
|
||||
global style
|
||||
style = dummy()
|
||||
|
||||
# Disable terminal coloring on Windows or if somebody's piping the output.
|
||||
if sys.platform == 'win32' or not sys.stdout.isatty():
|
||||
# Disable terminal coloring on Windows, Pocket PC, or if somebody's piping the output.
|
||||
if sys.platform == 'win32' or sys.platform == 'Pocket PC' or not sys.stdout.isatty():
|
||||
disable_termcolors()
|
||||
|
||||
def _is_valid_dir_name(s):
|
||||
@ -78,7 +78,7 @@ def get_version():
|
||||
from django import VERSION
|
||||
v = '.'.join([str(i) for i in VERSION[:-1]])
|
||||
if VERSION[-1]:
|
||||
v += ' (%s)' % VERSION[-1]
|
||||
v += '-' + VERSION[-1]
|
||||
return v
|
||||
|
||||
def get_sql_create(app):
|
||||
@ -95,44 +95,39 @@ def get_sql_create(app):
|
||||
sys.exit(1)
|
||||
|
||||
# Get installed models, so we generate REFERENCES right
|
||||
installed_models = _get_installed_models(_get_table_list())
|
||||
|
||||
final_output = []
|
||||
models_output = set(installed_models)
|
||||
known_models = set(_get_installed_models(_get_table_list()))
|
||||
pending_references = {}
|
||||
|
||||
app_models = models.get_models(app)
|
||||
|
||||
for klass in app_models:
|
||||
output, references = _get_sql_model_create(klass, models_output)
|
||||
for model in app_models:
|
||||
output, references = _get_sql_model_create(model, known_models)
|
||||
final_output.extend(output)
|
||||
for refto, refs in references.items():
|
||||
try:
|
||||
pending_references[refto].extend(refs)
|
||||
except KeyError:
|
||||
pending_references[refto] = refs
|
||||
final_output.extend(_get_sql_for_pending_references(klass, pending_references))
|
||||
pending_references.setdefault(refto,[]).extend(refs)
|
||||
final_output.extend(_get_sql_for_pending_references(model, pending_references))
|
||||
# Keep track of the fact that we've created the table for this model.
|
||||
models_output.add(klass)
|
||||
known_models.add(model)
|
||||
|
||||
# Create the many-to-many join tables.
|
||||
for klass in app_models:
|
||||
final_output.extend(_get_many_to_many_sql_for_model(klass))
|
||||
for model in app_models:
|
||||
final_output.extend(_get_many_to_many_sql_for_model(model))
|
||||
|
||||
# Handle references to tables that are from other apps
|
||||
# but don't exist physically
|
||||
not_installed_models = set(pending_references.keys())
|
||||
if not_installed_models:
|
||||
final_output.append('-- The following references should be added but depend on non-existant tables:')
|
||||
for klass in not_installed_models:
|
||||
for model in not_installed_models:
|
||||
final_output.extend(['-- ' + sql for sql in
|
||||
_get_sql_for_pending_references(klass, pending_references)])
|
||||
_get_sql_for_pending_references(model, pending_references)])
|
||||
|
||||
return final_output
|
||||
get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)."
|
||||
get_sql_create.args = APP_ARGS
|
||||
|
||||
def _get_sql_model_create(klass, models_already_seen=set()):
|
||||
def _get_sql_model_create(model, known_models=set()):
|
||||
"""
|
||||
Get the SQL required to create a single model.
|
||||
|
||||
@ -141,7 +136,7 @@ def _get_sql_model_create(klass, models_already_seen=set()):
|
||||
from django.db import backend, get_creation_module, models
|
||||
data_types = get_creation_module().DATA_TYPES
|
||||
|
||||
opts = klass._meta
|
||||
opts = model._meta
|
||||
final_output = []
|
||||
table_output = []
|
||||
pending_references = {}
|
||||
@ -163,7 +158,7 @@ def _get_sql_model_create(klass, models_already_seen=set()):
|
||||
if f.primary_key:
|
||||
field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
|
||||
if f.rel:
|
||||
if f.rel.to in models_already_seen:
|
||||
if f.rel.to in known_models:
|
||||
field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
|
||||
style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \
|
||||
style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')'
|
||||
@ -171,7 +166,7 @@ def _get_sql_model_create(klass, models_already_seen=set()):
|
||||
else:
|
||||
# We haven't yet created the table to which this field
|
||||
# is related, so save it for later.
|
||||
pr = pending_references.setdefault(f.rel.to, []).append((klass, f))
|
||||
pr = pending_references.setdefault(f.rel.to, []).append((model, f))
|
||||
table_output.append(' '.join(field_output))
|
||||
if opts.order_with_respect_to:
|
||||
table_output.append(style.SQL_FIELD(backend.quote_name('_order')) + ' ' + \
|
||||
@ -189,7 +184,7 @@ def _get_sql_model_create(klass, models_already_seen=set()):
|
||||
|
||||
return final_output, pending_references
|
||||
|
||||
def _get_sql_for_pending_references(klass, pending_references):
|
||||
def _get_sql_for_pending_references(model, pending_references):
|
||||
"""
|
||||
Get any ALTER TABLE statements to add constraints after the fact.
|
||||
"""
|
||||
@ -198,28 +193,30 @@ def _get_sql_for_pending_references(klass, pending_references):
|
||||
|
||||
final_output = []
|
||||
if backend.supports_constraints:
|
||||
opts = klass._meta
|
||||
if klass in pending_references:
|
||||
for rel_class, f in pending_references[klass]:
|
||||
opts = model._meta
|
||||
if model in pending_references:
|
||||
for rel_class, f in pending_references[model]:
|
||||
rel_opts = rel_class._meta
|
||||
r_table = rel_opts.db_table
|
||||
r_col = f.column
|
||||
table = opts.db_table
|
||||
col = opts.get_field(f.rel.field_name).column
|
||||
# For MySQL, r_name must be unique in the first 64 characters.
|
||||
# So we are careful with character usage here.
|
||||
r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
|
||||
final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
|
||||
(backend.quote_name(r_table),
|
||||
backend.quote_name('%s_referencing_%s_%s' % (r_col, table, col)),
|
||||
(backend.quote_name(r_table), r_name,
|
||||
backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
|
||||
del pending_references[klass]
|
||||
del pending_references[model]
|
||||
return final_output
|
||||
|
||||
def _get_many_to_many_sql_for_model(klass):
|
||||
def _get_many_to_many_sql_for_model(model):
|
||||
from django.db import backend, get_creation_module
|
||||
from django.db.models import GenericRel
|
||||
|
||||
|
||||
data_types = get_creation_module().DATA_TYPES
|
||||
|
||||
opts = klass._meta
|
||||
opts = model._meta
|
||||
final_output = []
|
||||
for f in opts.many_to_many:
|
||||
if not isinstance(f.rel, GenericRel):
|
||||
@ -273,37 +270,37 @@ def get_sql_delete(app):
|
||||
|
||||
references_to_delete = {}
|
||||
app_models = models.get_models(app)
|
||||
for klass in app_models:
|
||||
if cursor and klass._meta.db_table in table_names:
|
||||
for model in app_models:
|
||||
if cursor and model._meta.db_table in table_names:
|
||||
# The table exists, so it needs to be dropped
|
||||
opts = klass._meta
|
||||
opts = model._meta
|
||||
for f in opts.fields:
|
||||
if f.rel and f.rel.to not in to_delete:
|
||||
references_to_delete.setdefault(f.rel.to, []).append( (klass, f) )
|
||||
references_to_delete.setdefault(f.rel.to, []).append( (model, f) )
|
||||
|
||||
to_delete.add(klass)
|
||||
to_delete.add(model)
|
||||
|
||||
for klass in app_models:
|
||||
if cursor and klass._meta.db_table in table_names:
|
||||
for model in app_models:
|
||||
if cursor and model._meta.db_table in table_names:
|
||||
# Drop the table now
|
||||
output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'),
|
||||
style.SQL_TABLE(backend.quote_name(klass._meta.db_table))))
|
||||
if backend.supports_constraints and references_to_delete.has_key(klass):
|
||||
for rel_class, f in references_to_delete[klass]:
|
||||
style.SQL_TABLE(backend.quote_name(model._meta.db_table))))
|
||||
if backend.supports_constraints and references_to_delete.has_key(model):
|
||||
for rel_class, f in references_to_delete[model]:
|
||||
table = rel_class._meta.db_table
|
||||
col = f.column
|
||||
r_table = klass._meta.db_table
|
||||
r_col = klass._meta.get_field(f.rel.field_name).column
|
||||
r_table = model._meta.db_table
|
||||
r_col = model._meta.get_field(f.rel.field_name).column
|
||||
output.append('%s %s %s %s;' % \
|
||||
(style.SQL_KEYWORD('ALTER TABLE'),
|
||||
style.SQL_TABLE(backend.quote_name(table)),
|
||||
style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
|
||||
style.SQL_FIELD(backend.quote_name("%s_referencing_%s_%s" % (col, r_table, r_col)))))
|
||||
del references_to_delete[klass]
|
||||
del references_to_delete[model]
|
||||
|
||||
# Output DROP TABLE statements for many-to-many tables.
|
||||
for klass in app_models:
|
||||
opts = klass._meta
|
||||
for model in app_models:
|
||||
opts = model._meta
|
||||
for f in opts.many_to_many:
|
||||
if cursor and f.m2m_db_table() in table_names:
|
||||
output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'),
|
||||
@ -360,8 +357,8 @@ def get_sql_initial_data(app):
|
||||
app_models = get_models(app)
|
||||
app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql'))
|
||||
|
||||
for klass in app_models:
|
||||
output.extend(get_sql_initial_data_for_model(klass))
|
||||
for model in app_models:
|
||||
output.extend(get_sql_initial_data_for_model(model))
|
||||
|
||||
return output
|
||||
get_sql_initial_data.help_doc = "Prints the initial INSERT SQL statements for the given app name(s)."
|
||||
@ -371,18 +368,18 @@ def get_sql_sequence_reset(app):
|
||||
"Returns a list of the SQL statements to reset PostgreSQL sequences for the given app."
|
||||
from django.db import backend, models
|
||||
output = []
|
||||
for klass in models.get_models(app):
|
||||
for f in klass._meta.fields:
|
||||
for model in models.get_models(app):
|
||||
for f in model._meta.fields:
|
||||
if isinstance(f, models.AutoField):
|
||||
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
|
||||
(style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD('%s_%s_seq' % (klass._meta.db_table, f.column)),
|
||||
style.SQL_FIELD('%s_%s_seq' % (model._meta.db_table, f.column)),
|
||||
style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD(backend.quote_name(f.column)),
|
||||
style.SQL_KEYWORD('FROM'),
|
||||
style.SQL_TABLE(backend.quote_name(klass._meta.db_table))))
|
||||
style.SQL_TABLE(backend.quote_name(model._meta.db_table))))
|
||||
break # Only one AutoField is allowed per model, so don't bother continuing.
|
||||
for f in klass._meta.many_to_many:
|
||||
for f in model._meta.many_to_many:
|
||||
output.append("%s setval('%s', (%s max(%s) %s %s));" % \
|
||||
(style.SQL_KEYWORD('SELECT'),
|
||||
style.SQL_FIELD('%s_id_seq' % f.m2m_db_table()),
|
||||
@ -399,15 +396,15 @@ def get_sql_indexes(app):
|
||||
from django.db import backend, models
|
||||
output = []
|
||||
|
||||
for klass in models.get_models(app):
|
||||
for f in klass._meta.fields:
|
||||
for model in models.get_models(app):
|
||||
for f in model._meta.fields:
|
||||
if f.db_index:
|
||||
unique = f.unique and 'UNIQUE ' or ''
|
||||
output.append(
|
||||
style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
|
||||
style.SQL_TABLE('%s_%s' % (klass._meta.db_table, f.column)) + ' ' + \
|
||||
style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \
|
||||
style.SQL_KEYWORD('ON') + ' ' + \
|
||||
style.SQL_TABLE(backend.quote_name(klass._meta.db_table)) + ' ' + \
|
||||
style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
|
||||
"(%s);" % style.SQL_FIELD(backend.quote_name(f.column))
|
||||
)
|
||||
return output
|
||||
@ -517,14 +514,14 @@ def get_admin_index(app):
|
||||
app_label = app_models[0]._meta.app_label
|
||||
output.append('{%% if perms.%s %%}' % app_label)
|
||||
output.append('<div class="module"><h2>%s</h2><table>' % app_label.title())
|
||||
for klass in app_models:
|
||||
if klass._meta.admin:
|
||||
for model in app_models:
|
||||
if model._meta.admin:
|
||||
output.append(MODULE_TEMPLATE % {
|
||||
'app': app_label,
|
||||
'mod': klass._meta.module_name,
|
||||
'name': capfirst(klass._meta.verbose_name_plural),
|
||||
'addperm': klass._meta.get_add_permission(),
|
||||
'changeperm': klass._meta.get_change_permission(),
|
||||
'mod': model._meta.module_name,
|
||||
'name': capfirst(model._meta.verbose_name_plural),
|
||||
'addperm': model._meta.get_add_permission(),
|
||||
'changeperm': model._meta.get_change_permission(),
|
||||
})
|
||||
output.append('</table></div>')
|
||||
output.append('{% endif %}')
|
||||
@ -592,7 +589,6 @@ install.args = APP_ARGS
|
||||
def reset(app):
|
||||
"Executes the equivalent of 'get_sql_reset' in the current database."
|
||||
from django.db import connection, transaction
|
||||
from cStringIO import StringIO
|
||||
app_name = app.__name__.split('.')[-2]
|
||||
|
||||
disable_termcolors()
|
||||
@ -692,7 +688,6 @@ startapp.args = "[appname]"
|
||||
def inspectdb():
|
||||
"Generator that introspects the tables in the given database name and returns a Django model, one line at a time."
|
||||
from django.db import connection, get_introspection_module
|
||||
from django.conf import settings
|
||||
import keyword
|
||||
|
||||
introspection_module = get_introspection_module()
|
||||
@ -803,9 +798,9 @@ class ModelErrorCollection:
|
||||
self.errors = []
|
||||
self.outfile = outfile
|
||||
|
||||
def add(self, opts, error):
|
||||
self.errors.append((opts, error))
|
||||
self.outfile.write(style.ERROR("%s.%s: %s\n" % (opts.app_label, opts.module_name, error)))
|
||||
def add(self, context, error):
|
||||
self.errors.append((context, error))
|
||||
self.outfile.write(style.ERROR("%s: %s\n" % (context, error)))
|
||||
|
||||
def get_validation_errors(outfile, app=None):
|
||||
"""
|
||||
@ -814,9 +809,14 @@ def get_validation_errors(outfile, app=None):
|
||||
Returns number of errors.
|
||||
"""
|
||||
from django.db import models
|
||||
from django.db.models.loading import get_app_errors
|
||||
from django.db.models.fields.related import RelatedObject
|
||||
|
||||
e = ModelErrorCollection(outfile)
|
||||
|
||||
for (app_name, error) in get_app_errors().items():
|
||||
e.add(app_name, error)
|
||||
|
||||
for cls in models.get_models(app):
|
||||
opts = cls._meta
|
||||
|
||||
@ -858,18 +858,29 @@ def get_validation_errors(outfile, app=None):
|
||||
e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, rel_opts.object_name))
|
||||
|
||||
rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
|
||||
rel_query_name = f.related_query_name()
|
||||
for r in rel_opts.fields:
|
||||
if r.name == rel_name:
|
||||
e.add(opts, "'%s' accessor name '%s.%s' clashes with another field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
e.add(opts, "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
if r.name == rel_query_name:
|
||||
e.add(opts, "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
for r in rel_opts.many_to_many:
|
||||
if r.name == rel_name:
|
||||
e.add(opts, "'%s' accessor name '%s.%s' clashes with a m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
e.add(opts, "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
if r.name == rel_query_name:
|
||||
e.add(opts, "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
for r in rel_opts.get_all_related_many_to_many_objects():
|
||||
if r.get_accessor_name() == rel_name:
|
||||
e.add(opts, "'%s' accessor name '%s.%s' clashes with a related m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
e.add(opts, "Accessor for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
if r.get_accessor_name() == rel_query_name:
|
||||
e.add(opts, "Reverse query name for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
for r in rel_opts.get_all_related_objects():
|
||||
if r.get_accessor_name() == rel_name and r.field is not f:
|
||||
e.add(opts, "'%s' accessor name '%s.%s' clashes with another related field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
if r.field is not f:
|
||||
if r.get_accessor_name() == rel_name:
|
||||
e.add(opts, "Accessor for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
if r.get_accessor_name() == rel_query_name:
|
||||
e.add(opts, "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
|
||||
|
||||
for i, f in enumerate(opts.many_to_many):
|
||||
# Check to see if the related m2m field will clash with any
|
||||
@ -879,18 +890,28 @@ def get_validation_errors(outfile, app=None):
|
||||
e.add(opts, "'%s' has m2m relation with model %s, which has not been installed" % (f.name, rel_opts.object_name))
|
||||
|
||||
rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
|
||||
rel_query_name = f.related_query_name()
|
||||
for r in rel_opts.fields:
|
||||
if r.name == rel_name:
|
||||
e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with another field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
if r.name == rel_query_name:
|
||||
e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
for r in rel_opts.many_to_many:
|
||||
if r.name == rel_name:
|
||||
e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with a m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
if r.name == rel_query_name:
|
||||
e.add(opts, "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
|
||||
for r in rel_opts.get_all_related_many_to_many_objects():
|
||||
if r.get_accessor_name() == rel_name and r.field is not f:
|
||||
e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with a related m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
if r.field is not f:
|
||||
if r.get_accessor_name() == rel_name:
|
||||
e.add(opts, "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
if r.get_accessor_name() == rel_query_name:
|
||||
e.add(opts, "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
for r in rel_opts.get_all_related_objects():
|
||||
if r.get_accessor_name() == rel_name:
|
||||
e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with another related field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
e.add(opts, "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
if r.get_accessor_name() == rel_query_name:
|
||||
e.add(opts, "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
|
||||
|
||||
# Check admin attribute.
|
||||
if opts.admin is not None:
|
||||
@ -910,6 +931,19 @@ def get_validation_errors(outfile, app=None):
|
||||
else:
|
||||
if isinstance(f, models.ManyToManyField):
|
||||
e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn)
|
||||
# list_display_links
|
||||
if opts.admin.list_display_links and not opts.admin.list_display:
|
||||
e.add(opts, '"admin.list_display" must be defined for "admin.list_display_links" to be used.')
|
||||
if not isinstance(opts.admin.list_display_links, (list, tuple)):
|
||||
e.add(opts, '"admin.list_display_links", if given, must be set to a list or tuple.')
|
||||
else:
|
||||
for fn in opts.admin.list_display_links:
|
||||
try:
|
||||
f = opts.get_field(fn)
|
||||
except models.FieldDoesNotExist:
|
||||
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
|
||||
if fn not in opts.admin.list_display:
|
||||
e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn)
|
||||
# list_filter
|
||||
if not isinstance(opts.admin.list_filter, (list, tuple)):
|
||||
e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.')
|
||||
@ -919,6 +953,12 @@ def get_validation_errors(outfile, app=None):
|
||||
f = opts.get_field(fn)
|
||||
except models.FieldDoesNotExist:
|
||||
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
|
||||
# date_hierarchy
|
||||
if opts.admin.date_hierarchy:
|
||||
try:
|
||||
f = opts.get_field(opts.admin.date_hierarchy)
|
||||
except models.FieldDoesNotExist:
|
||||
e.add(opts, '"admin.date_hierarchy" refers to %r, which isn\'t a field.' % opts.admin.date_hierarchy)
|
||||
|
||||
# Check ordering attribute.
|
||||
if opts.ordering:
|
||||
@ -936,6 +976,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:
|
||||
@ -975,12 +1017,15 @@ 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)
|
||||
|
||||
def runserver(addr, port):
|
||||
def runserver(addr, port, use_reloader=True):
|
||||
"Starts a lightweight Web server for development."
|
||||
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
|
||||
from django.core.handlers.wsgi import WSGIHandler
|
||||
@ -1014,9 +1059,12 @@ def runserver(addr, port):
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
||||
from django.utils import autoreload
|
||||
autoreload.main(inner_run)
|
||||
runserver.args = '[optional port number, or ipaddr:port]'
|
||||
if use_reloader:
|
||||
from django.utils import autoreload
|
||||
autoreload.main(inner_run)
|
||||
else:
|
||||
inner_run()
|
||||
runserver.args = '[--noreload] [optional port number, or ipaddr:port]'
|
||||
|
||||
def createcachetable(tablename):
|
||||
"Creates the table needed to use the SQL cache backend"
|
||||
@ -1165,6 +1213,8 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
||||
help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
|
||||
parser.add_option('--plain', action='store_true', dest='plain',
|
||||
help='Tells Django to use plain Python, not IPython, for "shell" command.')
|
||||
parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
|
||||
help='Tells Django to NOT use the auto-reloader when running the development server.')
|
||||
options, args = parser.parse_args(argv[1:])
|
||||
|
||||
# Take care of options.
|
||||
@ -1220,7 +1270,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
||||
addr, port = args[1].split(':')
|
||||
except ValueError:
|
||||
addr, port = '', args[1]
|
||||
action_mapping[action](addr, port)
|
||||
action_mapping[action](addr, port, options.use_reloader)
|
||||
elif action == 'runfcgi':
|
||||
action_mapping[action](args[1:])
|
||||
else:
|
||||
|
@ -1,4 +1,3 @@
|
||||
from copy import copy
|
||||
from math import ceil
|
||||
|
||||
class InvalidPage(Exception):
|
||||
|
78
django/core/serializers/__init__.py
Normal file
78
django/core/serializers/__init__.py
Normal file
@ -0,0 +1,78 @@
|
||||
"""
|
||||
Interfaces for serializing Django objects.
|
||||
|
||||
Usage::
|
||||
|
||||
>>> from django.core import serializers
|
||||
>>> json = serializers.serialize("json", some_query_set)
|
||||
>>> objects = list(serializers.deserialize("json", json))
|
||||
|
||||
To add your own serializers, use the SERIALIZATION_MODULES setting::
|
||||
|
||||
SERIALIZATION_MODULES = {
|
||||
"csv" : "path.to.csv.serializer",
|
||||
"txt" : "path.to.txt.serializer",
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
# Built-in serializers
|
||||
BUILTIN_SERIALIZERS = {
|
||||
"xml" : "django.core.serializers.xml_serializer",
|
||||
"python" : "django.core.serializers.python",
|
||||
"json" : "django.core.serializers.json",
|
||||
}
|
||||
|
||||
_serializers = {}
|
||||
|
||||
def register_serializer(format, serializer_module):
|
||||
"""Register a new serializer by passing in a module name."""
|
||||
module = __import__(serializer_module, '', '', [''])
|
||||
_serializers[format] = module
|
||||
|
||||
def unregister_serializer(format):
|
||||
"""Unregister a given serializer"""
|
||||
del _serializers[format]
|
||||
|
||||
def get_serializer(format):
|
||||
if not _serializers:
|
||||
_load_serializers()
|
||||
return _serializers[format].Serializer
|
||||
|
||||
def get_deserializer(format):
|
||||
if not _serializers:
|
||||
_load_serializers()
|
||||
return _serializers[format].Deserializer
|
||||
|
||||
def serialize(format, queryset, **options):
|
||||
"""
|
||||
Serialize a queryset (or any iterator that returns database objects) using
|
||||
a certain serializer.
|
||||
"""
|
||||
s = get_serializer(format)()
|
||||
s.serialize(queryset, **options)
|
||||
return s.getvalue()
|
||||
|
||||
def deserialize(format, stream_or_string):
|
||||
"""
|
||||
Deserialize a stream or a string. Returns an iterator that yields ``(obj,
|
||||
m2m_relation_dict)``, where ``obj`` is a instantiated -- but *unsaved* --
|
||||
object, and ``m2m_relation_dict`` is a dictionary of ``{m2m_field_name :
|
||||
list_of_related_objects}``.
|
||||
"""
|
||||
d = get_deserializer(format)
|
||||
return d(stream_or_string)
|
||||
|
||||
def _load_serializers():
|
||||
"""
|
||||
Register built-in and settings-defined serializers. This is done lazily so
|
||||
that user code has a chance to (e.g.) set up custom settings without
|
||||
needing to be careful of import order.
|
||||
"""
|
||||
for format in BUILTIN_SERIALIZERS:
|
||||
register_serializer(format, BUILTIN_SERIALIZERS[format])
|
||||
if hasattr(settings, "SERIALIZATION_MODULES"):
|
||||
for format in settings.SERIALIZATION_MODULES:
|
||||
register_serializer(format, settings.SERIALIZATION_MODULES[format])
|
161
django/core/serializers/base.py
Normal file
161
django/core/serializers/base.py
Normal file
@ -0,0 +1,161 @@
|
||||
"""
|
||||
Module for abstract serializer/unserializer base classes.
|
||||
"""
|
||||
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
from django.db import models
|
||||
|
||||
class SerializationError(Exception):
|
||||
"""Something bad happened during serialization."""
|
||||
pass
|
||||
|
||||
class DeserializationError(Exception):
|
||||
"""Something bad happened during deserialization."""
|
||||
pass
|
||||
|
||||
class Serializer(object):
|
||||
"""
|
||||
Abstract serializer base class.
|
||||
"""
|
||||
|
||||
def serialize(self, queryset, **options):
|
||||
"""
|
||||
Serialize a queryset.
|
||||
"""
|
||||
self.options = options
|
||||
|
||||
self.stream = options.get("stream", StringIO())
|
||||
|
||||
self.start_serialization()
|
||||
for obj in queryset:
|
||||
self.start_object(obj)
|
||||
for field in obj._meta.fields:
|
||||
if field is obj._meta.pk:
|
||||
continue
|
||||
elif field.rel is None:
|
||||
self.handle_field(obj, field)
|
||||
else:
|
||||
self.handle_fk_field(obj, field)
|
||||
for field in obj._meta.many_to_many:
|
||||
self.handle_m2m_field(obj, field)
|
||||
self.end_object(obj)
|
||||
self.end_serialization()
|
||||
return self.getvalue()
|
||||
|
||||
def get_string_value(self, obj, field):
|
||||
"""
|
||||
Convert a field's value to a string.
|
||||
"""
|
||||
if isinstance(field, models.DateTimeField):
|
||||
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:
|
||||
value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
|
||||
return str(value)
|
||||
|
||||
def start_serialization(self):
|
||||
"""
|
||||
Called when serializing of the queryset starts.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def end_serialization(self):
|
||||
"""
|
||||
Called when serializing of the queryset ends.
|
||||
"""
|
||||
pass
|
||||
|
||||
def start_object(self, obj):
|
||||
"""
|
||||
Called when serializing of an object starts.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def end_object(self, obj):
|
||||
"""
|
||||
Called when serializing of an object ends.
|
||||
"""
|
||||
pass
|
||||
|
||||
def handle_field(self, obj, field):
|
||||
"""
|
||||
Called to handle each individual (non-relational) field on an object.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def handle_fk_field(self, obj, field):
|
||||
"""
|
||||
Called to handle a ForeignKey field.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def handle_m2m_field(self, obj, field):
|
||||
"""
|
||||
Called to handle a ManyToManyField.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def getvalue(self):
|
||||
"""
|
||||
Return the fully serialized queryset.
|
||||
"""
|
||||
return self.stream.getvalue()
|
||||
|
||||
class Deserializer(object):
|
||||
"""
|
||||
Abstract base deserializer class.
|
||||
"""
|
||||
|
||||
def __init__(self, stream_or_string, **options):
|
||||
"""
|
||||
Init this serializer given a stream or a string
|
||||
"""
|
||||
self.options = options
|
||||
if isinstance(stream_or_string, basestring):
|
||||
self.stream = StringIO(stream_or_string)
|
||||
else:
|
||||
self.stream = stream_or_string
|
||||
# hack to make sure that the models have all been loaded before
|
||||
# deserialization starts (otherwise subclass calls to get_model()
|
||||
# and friends might fail...)
|
||||
models.get_apps()
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
"""Iteration iterface -- return the next item in the stream"""
|
||||
raise NotImplementedError
|
||||
|
||||
class DeserializedObject(object):
|
||||
"""
|
||||
A deserialzed model.
|
||||
|
||||
Basically a container for holding the pre-saved deserialized data along
|
||||
with the many-to-many data saved with the object.
|
||||
|
||||
Call ``save()`` to save the object (with the many-to-many data) to the
|
||||
database; call ``save(save_m2m=False)`` to save just the object fields
|
||||
(and not touch the many-to-many stuff.)
|
||||
"""
|
||||
|
||||
def __init__(self, obj, m2m_data=None):
|
||||
self.object = obj
|
||||
self.m2m_data = m2m_data
|
||||
|
||||
def __repr__(self):
|
||||
return "<DeserializedObject: %s>" % str(self.object)
|
||||
|
||||
def save(self, save_m2m=True):
|
||||
self.object.save()
|
||||
if self.m2m_data and save_m2m:
|
||||
for accessor_name, object_list in self.m2m_data.items():
|
||||
setattr(self.object, accessor_name, object_list)
|
||||
|
||||
# prevent a second (possibly accidental) call to save() from saving
|
||||
# the m2m data twice.
|
||||
self.m2m_data = None
|
51
django/core/serializers/json.py
Normal file
51
django/core/serializers/json.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""
|
||||
Serialize data to/from JSON
|
||||
"""
|
||||
|
||||
import datetime
|
||||
from django.utils import simplejson
|
||||
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
|
||||
|
||||
class Serializer(PythonSerializer):
|
||||
"""
|
||||
Convert a queryset to JSON.
|
||||
"""
|
||||
def end_serialization(self):
|
||||
simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder)
|
||||
|
||||
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(simplejson.load(stream)):
|
||||
yield obj
|
||||
|
||||
class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
|
||||
"""
|
||||
JSONEncoder subclass that knows how to encode date/time types
|
||||
"""
|
||||
|
||||
DATE_FORMAT = "%Y-%m-%d"
|
||||
TIME_FORMAT = "%H:%M:%S"
|
||||
|
||||
def default(self, o):
|
||||
if isinstance(o, datetime.datetime):
|
||||
return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
|
||||
elif isinstance(o, datetime.date):
|
||||
return o.strftime(self.DATE_FORMAT)
|
||||
elif isinstance(o, datetime.time):
|
||||
return o.strftime(self.TIME_FORMAT)
|
||||
else:
|
||||
return super(self, DateTimeAwareJSONEncoder).default(o)
|
101
django/core/serializers/python.py
Normal file
101
django/core/serializers/python.py
Normal file
@ -0,0 +1,101 @@
|
||||
"""
|
||||
A Python "serializer". Doesn't do much serializing per se -- just converts to
|
||||
and from basic Python data types (lists, dicts, strings, etc.). Useful as a basis for
|
||||
other serializers.
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.serializers import base
|
||||
from django.db import models
|
||||
|
||||
class Serializer(base.Serializer):
|
||||
"""
|
||||
Serializes a QuerySet to basic Python objects.
|
||||
"""
|
||||
|
||||
def start_serialization(self):
|
||||
self._current = None
|
||||
self.objects = []
|
||||
|
||||
def end_serialization(self):
|
||||
pass
|
||||
|
||||
def start_object(self, obj):
|
||||
self._current = {}
|
||||
|
||||
def end_object(self, obj):
|
||||
self.objects.append({
|
||||
"model" : str(obj._meta),
|
||||
"pk" : str(obj._get_pk_val()),
|
||||
"fields" : self._current
|
||||
})
|
||||
self._current = None
|
||||
|
||||
def handle_field(self, obj, field):
|
||||
self._current[field.name] = getattr(obj, field.name)
|
||||
|
||||
def handle_fk_field(self, obj, field):
|
||||
related = getattr(obj, field.name)
|
||||
if related is not None:
|
||||
related = related._get_pk_val()
|
||||
self._current[field.name] = related
|
||||
|
||||
def handle_m2m_field(self, obj, field):
|
||||
self._current[field.name] = [related._get_pk_val() for related in getattr(obj, field.name).iterator()]
|
||||
|
||||
def getvalue(self):
|
||||
return self.objects
|
||||
|
||||
def Deserializer(object_list, **options):
|
||||
"""
|
||||
Deserialize simple Python objects back into Django ORM instances.
|
||||
|
||||
It's expected that you pass the Python objects themselves (instead of a
|
||||
stream or a string) to the constructor
|
||||
"""
|
||||
models.get_apps()
|
||||
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.name : d["pk"]}
|
||||
m2m_data = {}
|
||||
|
||||
# Handle each field
|
||||
for (field_name, field_value) in d["fields"].iteritems():
|
||||
if isinstance(field_value, unicode):
|
||||
field_value = field_value.encode(options.get("encoding", settings.DEFAULT_CHARSET))
|
||||
|
||||
field = Model._meta.get_field(field_name)
|
||||
|
||||
# Handle M2M relations (with in_bulk() for performance)
|
||||
if field.rel and isinstance(field.rel, models.ManyToManyRel):
|
||||
pks = []
|
||||
for pk in field_value:
|
||||
if isinstance(pk, unicode):
|
||||
pk = pk.encode(options.get("encoding", settings.DEFAULT_CHARSET))
|
||||
m2m_data[field.name] = field.rel.to._default_manager.in_bulk(field_value).values()
|
||||
|
||||
# Handle FK fields
|
||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
||||
try:
|
||||
data[field.name] = field.rel.to._default_manager.get(pk=field_value)
|
||||
except field.rel.to.DoesNotExist:
|
||||
data[field.name] = None
|
||||
|
||||
# Handle all other fields
|
||||
else:
|
||||
data[field.name] = field.to_python(field_value)
|
||||
|
||||
yield base.DeserializedObject(Model(**data), m2m_data)
|
||||
|
||||
def _get_model(model_identifier):
|
||||
"""
|
||||
Helper to look up a model from an "app_label.module_name" string.
|
||||
"""
|
||||
try:
|
||||
Model = models.get_model(*model_identifier.split("."))
|
||||
except TypeError:
|
||||
Model = None
|
||||
if Model is None:
|
||||
raise base.DeserializationError("Invalid model identifier: '%s'" % model_identifier)
|
||||
return Model
|
217
django/core/serializers/xml_serializer.py
Normal file
217
django/core/serializers/xml_serializer.py
Normal file
@ -0,0 +1,217 @@
|
||||
"""
|
||||
XML serializer.
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.serializers import base
|
||||
from django.db import models
|
||||
from django.utils.xmlutils import SimplerXMLGenerator
|
||||
from xml.dom import pulldom
|
||||
|
||||
class Serializer(base.Serializer):
|
||||
"""
|
||||
Serializes a QuerySet to XML.
|
||||
"""
|
||||
|
||||
def start_serialization(self):
|
||||
"""
|
||||
Start serialization -- open the XML document and the root element.
|
||||
"""
|
||||
self.xml = SimplerXMLGenerator(self.stream, self.options.get("encoding", settings.DEFAULT_CHARSET))
|
||||
self.xml.startDocument()
|
||||
self.xml.startElement("django-objects", {"version" : "1.0"})
|
||||
|
||||
def end_serialization(self):
|
||||
"""
|
||||
End serialization -- end the document.
|
||||
"""
|
||||
self.xml.endElement("django-objects")
|
||||
self.xml.endDocument()
|
||||
|
||||
def start_object(self, obj):
|
||||
"""
|
||||
Called as each object is handled.
|
||||
"""
|
||||
if not hasattr(obj, "_meta"):
|
||||
raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj))
|
||||
|
||||
self.xml.startElement("object", {
|
||||
"pk" : str(obj._get_pk_val()),
|
||||
"model" : str(obj._meta),
|
||||
})
|
||||
|
||||
def end_object(self, obj):
|
||||
"""
|
||||
Called after handling all fields for an object.
|
||||
"""
|
||||
self.xml.endElement("object")
|
||||
|
||||
def handle_field(self, obj, field):
|
||||
"""
|
||||
Called to handle each field on an object (except for ForeignKeys and
|
||||
ManyToManyFields)
|
||||
"""
|
||||
self.xml.startElement("field", {
|
||||
"name" : field.name,
|
||||
"type" : field.get_internal_type()
|
||||
})
|
||||
|
||||
# Get a "string version" of the object's data (this is handled by the
|
||||
# serializer base class). None is handled specially.
|
||||
value = self.get_string_value(obj, field)
|
||||
if value is not None:
|
||||
self.xml.characters(str(value))
|
||||
|
||||
self.xml.endElement("field")
|
||||
|
||||
def handle_fk_field(self, obj, field):
|
||||
"""
|
||||
Called to handle a ForeignKey (we need to treat them slightly
|
||||
differently from regular fields).
|
||||
"""
|
||||
self._start_relational_field(field)
|
||||
related = getattr(obj, field.name)
|
||||
if related is not None:
|
||||
self.xml.characters(str(related._get_pk_val()))
|
||||
else:
|
||||
self.xml.addQuickElement("None")
|
||||
self.xml.endElement("field")
|
||||
|
||||
def handle_m2m_field(self, obj, field):
|
||||
"""
|
||||
Called to handle a ManyToManyField. Related objects are only
|
||||
serialized as references to the object's PK (i.e. the related *data*
|
||||
is not dumped, just the relation).
|
||||
"""
|
||||
self._start_relational_field(field)
|
||||
for relobj in getattr(obj, field.name).iterator():
|
||||
self.xml.addQuickElement("object", attrs={"pk" : str(relobj._get_pk_val())})
|
||||
self.xml.endElement("field")
|
||||
|
||||
def _start_relational_field(self, field):
|
||||
"""
|
||||
Helper to output the <field> element for relational fields
|
||||
"""
|
||||
self.xml.startElement("field", {
|
||||
"name" : field.name,
|
||||
"rel" : field.rel.__class__.__name__,
|
||||
"to" : str(field.rel.to._meta),
|
||||
})
|
||||
|
||||
class Deserializer(base.Deserializer):
|
||||
"""
|
||||
Deserialize XML.
|
||||
"""
|
||||
|
||||
def __init__(self, stream_or_string, **options):
|
||||
super(Deserializer, self).__init__(stream_or_string, **options)
|
||||
self.encoding = self.options.get("encoding", settings.DEFAULT_CHARSET)
|
||||
self.event_stream = pulldom.parse(self.stream)
|
||||
|
||||
def next(self):
|
||||
for event, node in self.event_stream:
|
||||
if event == "START_ELEMENT" and node.nodeName == "object":
|
||||
self.event_stream.expandNode(node)
|
||||
return self._handle_object(node)
|
||||
raise StopIteration
|
||||
|
||||
def _handle_object(self, node):
|
||||
"""
|
||||
Convert an <object> node to a DeserializedObject.
|
||||
"""
|
||||
# Look up the model using the model loading mechanism. If this fails, bail.
|
||||
Model = self._get_model_from_node(node, "model")
|
||||
|
||||
# Start building a data dictionary from the object. If the node is
|
||||
# missing the pk attribute, bail.
|
||||
pk = node.getAttribute("pk")
|
||||
if not pk:
|
||||
raise base.DeserializationError("<object> node is missing the 'pk' attribute")
|
||||
data = {Model._meta.pk.name : pk}
|
||||
|
||||
# Also start building a dict of m2m data (this is saved as
|
||||
# {m2m_accessor_attribute : [list_of_related_objects]})
|
||||
m2m_data = {}
|
||||
|
||||
# Deseralize each field.
|
||||
for field_node in node.getElementsByTagName("field"):
|
||||
# If the field is missing the name attribute, bail (are you
|
||||
# sensing a pattern here?)
|
||||
field_name = field_node.getAttribute("name")
|
||||
if not field_name:
|
||||
raise base.DeserializationError("<field> node is missing the 'name' attribute")
|
||||
|
||||
# Get the field from the Model. This will raise a
|
||||
# FieldDoesNotExist if, well, the field doesn't exist, which will
|
||||
# be propagated correctly.
|
||||
field = Model._meta.get_field(field_name)
|
||||
|
||||
# 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)
|
||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
||||
data[field.name] = self._handle_fk_field_node(field_node)
|
||||
else:
|
||||
value = field.to_python(getInnerText(field_node).strip().encode(self.encoding))
|
||||
data[field.name] = value
|
||||
|
||||
# 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):
|
||||
"""
|
||||
Handle a <field> node for a ForeignKey
|
||||
"""
|
||||
# Try to set the foreign key by looking up the foreign related object.
|
||||
# If it doesn't exist, set the field to None (which might trigger
|
||||
# validation error, but that's expected).
|
||||
RelatedModel = self._get_model_from_node(node, "to")
|
||||
return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding))
|
||||
|
||||
def _handle_m2m_field_node(self, node):
|
||||
"""
|
||||
Handle a <field> node for a ManyToManyField
|
||||
"""
|
||||
# Load the related model
|
||||
RelatedModel = self._get_model_from_node(node, "to")
|
||||
|
||||
# Look up all the related objects. Using the in_bulk() lookup ensures
|
||||
# that missing related objects don't cause an exception
|
||||
related_ids = [c.getAttribute("pk").encode(self.encoding) for c in node.getElementsByTagName("object")]
|
||||
return RelatedModel._default_manager.in_bulk(related_ids).values()
|
||||
|
||||
def _get_model_from_node(self, node, attr):
|
||||
"""
|
||||
Helper to look up a model from a <object model=...> or a <field
|
||||
rel=... to=...> node.
|
||||
"""
|
||||
model_identifier = node.getAttribute(attr)
|
||||
if not model_identifier:
|
||||
raise base.DeserializationError(
|
||||
"<%s> node is missing the required '%s' attribute" \
|
||||
% (node.nodeName, attr))
|
||||
try:
|
||||
Model = models.get_model(*model_identifier.split("."))
|
||||
except TypeError:
|
||||
Model = None
|
||||
if Model is None:
|
||||
raise base.DeserializationError(
|
||||
"<%s> node has invalid model identifier: '%s'" % \
|
||||
(node.nodeName, model_identifier))
|
||||
return Model
|
||||
|
||||
|
||||
def getInnerText(node):
|
||||
"""
|
||||
Get all the inner text of a DOM node (recursively).
|
||||
"""
|
||||
# inspired by http://mail.python.org/pipermail/xml-sig/2005-March/011022.html
|
||||
inner_text = []
|
||||
for child in node.childNodes:
|
||||
if child.nodeType == child.TEXT_NODE or child.nodeType == child.CDATA_SECTION_NODE:
|
||||
inner_text.append(child.data)
|
||||
elif child.nodeType == child.ELEMENT_NODE:
|
||||
inner_text.extend(getInnerText(child))
|
||||
else:
|
||||
pass
|
||||
return "".join(inner_text)
|
@ -8,7 +8,7 @@ been reviewed for security issues. Don't use it for production use.
|
||||
"""
|
||||
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
from types import ListType, StringType, TupleType
|
||||
from types import ListType, StringType
|
||||
import os, re, sys, time, urllib
|
||||
|
||||
__version__ = "0.1"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user