1
0
mirror of https://github.com/django/django.git synced 2025-07-04 01:39:20 +00:00

gis: Made necessary modifications for unicode, manage refactor, backend refactor and merged 5584-6000 via svnmerge from [repos:django/trunk trunk].

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6018 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2007-08-26 01:10:53 +00:00
parent a7297a255f
commit 2052b508eb
405 changed files with 29980 additions and 17232 deletions

46
AUTHORS
View File

@ -44,6 +44,7 @@ answer newbie questions, and generally made Django that much better:
alang@bright-green.com
Marty Alchin <gulopine@gamemusic.org>
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
AgarFu <heaven@croasanaso.sytes.net>
Andreas
andy@jadedplanet.net
Fabrice Aneche <akh@nobugware.com>
@ -56,15 +57,21 @@ answer newbie questions, and generally made Django that much better:
Ned Batchelder <http://www.nedbatchelder.com/>
Shannon -jj Behrens <http://jjinux.blogspot.com/>
Esdras Beleza <linux@esdrasbeleza.com>
Chris Bennett <chrisrbennett@yahoo.com>
James Bennett
Ben <afternoon@uk2.net>
Paul Bissex <http://e-scribe.com/>
Simon Blanchard
Matt Boersma <ogghead@gmail.com>
boobsd@gmail.com
Andrew Brehaut <http://brehaut.net/blog>
brut.alll@gmail.com
Jonathan Buchanan <jonathan.buchanan@gmail.com>
Trevor Caira <trevor@caira.com>
Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com>
Antonio Cavedoni <http://cavedoni.com/>
C8E
cedric@terramater.net
Chris Chamberlin <dja@cdc.msbx.net>
Amit Chakradeo <http://amit.chakradeo.net/>
ChaosKCW
@ -72,6 +79,7 @@ answer newbie questions, and generally made Django that much better:
Bryan Chow <bryan at verdjn dot com>
Michal Chruszcz <troll@pld-linux.org>
Ian Clelland <clelland@gmail.com>
colin@owlfish.com
crankycoder@gmail.com
Pete Crosier <pete.crosier@gmail.com>
Matt Croydon <http://www.postneo.com/>
@ -91,10 +99,14 @@ answer newbie questions, and generally made Django that much better:
Maximillian Dornseif <md@hudora.de>
Jeremy Dunck <http://dunck.us/>
Andrew Durdin <adurdin@gmail.com>
dusk@woofle.net
Andy Dustman <farcepest@gmail.com>
Clint Ecker
Nick Efford <nick@efford.org>
eibaan@gmail.com
enlight
Enrico <rico.bl@gmail.com>
A. Murat Eren <meren@pardus.org.tr>
Ludvig Ericson <ludvig.ericson@gmail.com>
Dirk Eschler <dirk.eschler@gmx.net>
Marc Fargas <telenieko@telenieko.com>
@ -106,19 +118,26 @@ answer newbie questions, and generally made Django that much better:
Eric Floehr <eric@intellovations.com>
Jorge Gajon <gajon@gajon.org>
gandalf@owca.info
Marc Garcia <marc.garcia@accopensys.com>
Baishampayan Ghose
glin@seznam.cz
martin.glueck@gmail.com
GomoX <gomo@datafull.com>
Mario Gonzalez <gonzalemario@gmail.com>
pradeep.gowda@gmail.com
Simon Greenhill <dev@simon.net.nz>
Owen Griffiths
Espen Grindhaug <http://grindhaug.org/>
Thomas Güttler <hv@tbz-pariv.de>
dAniel hAhler
Brian Harring <ferringb@gmail.com>
Brant Harris
Hawkeye
Joe Heck <http://www.rhonabwy.com/wp/>
Joel Heenan <joelh-django@planetjoel.com>
hipertracker@gmail.com
Deryck Hodge <http://www.devurandom.org/>
Brett Hoerner <bretthoerner@bretthoerner.com>
Ian Holsman <http://feh.holsman.net/>
Kieran Holland <http://www.kieranholland.com>
Sung-Jin Hong <serialx.net@gmail.com>
@ -128,6 +147,7 @@ answer newbie questions, and generally made Django that much better:
Hyun Mi Ae
Tom Insam
Baurzhan Ismagulov <ibr@radix50.net>
james_027@yahoo.com
jcrasta@gmail.com
Zak Johnson <zakj@nox.cx>
Michael Josephson <http://www.sdjournal.com/>
@ -135,18 +155,23 @@ answer newbie questions, and generally made Django that much better:
junzhang.jn@gmail.com
Antti Kaihola <http://akaihola.blogspot.com/>
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
ian.g.kelly@gmail.com
Ian G. Kelly <ian.g.kelly@gmail.com>
Ben Khoo <khoobks@westnet.com.au>
Garth Kidd <http://www.deadlybloodyserious.com/>
kilian <kilian.cavalotti@lip6.fr>
Sune Kirkeby <http://ibofobi.dk/>
Bastian Kleineidam <calvin@debian.org>
Cameron Knight (ckknight)
Nena Kojadin <nena@kiberpipa.org>
Igor Kolar <ike@email.si>
Gasper Koren
Martin Kosír <martin@martinkosir.net>
Meir Kriheli <http://mksoft.co.il/>
Bruce Kroeze <http://coderseye.com/>
krzysiek.pawlik@silvermedia.pl
Joseph Kocherhans
konrad@gwu.edu
kurtiss@meetro.com
lakin.wecker@gmail.com
Nick Lane <nick.lane.au@gmail.com>
Stuart Langridge <http://www.kryogenix.org/>
@ -158,13 +183,14 @@ answer newbie questions, and generally made Django that much better:
lerouxb@gmail.com
Waylan Limberg <waylan@gmail.com>
limodou
Philip Lindborg <philip.lindborg@gmail.com>
Matt McClanahan <http://mmcc.cx/>
Martin Maney <http://www.chipy.org/Martin_Maney>
masonsimon+django@gmail.com
Manuzhai
Petar Marić <http://www.petarmaric.com/>
Nuno Mariz <nmariz@gmail.com>
marijn@metronomo.cl
Marijn Vriens <marijn@metronomo.cl>
mark@junklight.com
Yasushi Masuda <whosaysni@gmail.com>
mattycakes@gmail.com
@ -172,9 +198,13 @@ answer newbie questions, and generally made Django that much better:
mccutchen@gmail.com
michael.mcewan@gmail.com
mikko@sorl.net
Slawek Mikula <slawek dot mikula at gmail dot com>
mitakummaa@gmail.com
mmarshall
Andreas Mock <andreas.mock@web.de>
Reza Mohammadi <reza@zeerak.ir>
Aljosa Mohorovic <aljosa.mohorovic@gmail.com>
Ramiro Morales <rm0@gmx.net>
Eric Moritz <http://eric.themoritzfamily.com/>
mrmachine <real.human@mrmachine.net>
Robin Munn <http://www.geekforgod.com/>
@ -184,6 +214,7 @@ answer newbie questions, and generally made Django that much better:
Fraser Nevett <mail@nevett.org>
Sam Newman <http://www.magpiebrain.com/>
Neal Norwitz <nnorwitz@google.com>
Todd O'Bryan <toddobryan@mac.com>
oggie rob <oz.robharvey@gmail.com>
Jay Parlar <parlar@gmail.com>
pavithran s <pavithran.s@gmail.com>
@ -198,22 +229,26 @@ answer newbie questions, and generally made Django that much better:
plisk
Daniel Poelzleithner <http://poelzi.org/>
polpak@yahoo.com
Jyrki Pulliainen <jyrki.pulliainen@gmail.com>
Johann Queuniet <johann.queuniet@adh.naellia.eu>
J. Rademaker
Michael Radziej <mir@noris.de>
Ramiro Morales <rm0@gmx.net>
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
Brian Ray <http://brianray.chipy.org/>
remco@diji.biz
rhettg@gmail.com
Henrique Romano <onaiort@gmail.com>
Armin Ronacher
Brian Rosner <brosner@gmail.com>
Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
Vinay Sajip <vinay_sajip@yahoo.co.uk>
David Schein
scott@staplefish.com
serbaut@gmail.com
John Shaffer <jshaffer2112@gmail.com>
Pete Shinners <pete@shinners.org>
Jozko Skrablin <jozko.skrablin@gmail.com>
SmileyChris <smileychris@gmail.com>
smurf@smurf.noris.de
sopel
@ -222,6 +257,8 @@ answer newbie questions, and generally made Django that much better:
Vasiliy Stavenko <stavenko@gmail.com>
Thomas Steinacher <http://www.eggdrop.ch/>
nowell strite
Sundance
SuperJared
Radek Švarz <http://www.svarz.cz/translate/>
Swaroop C H <http://www.swaroopch.info>
Aaron Swartz <http://www.aaronsw.com/>
@ -231,10 +268,12 @@ answer newbie questions, and generally made Django that much better:
thebjorn <bp@datakortet.no>
Zach Thompson <zthompson47@gmail.com>
tibimicu@gmax.net
tobias@neuyork.de
Tom Tobin
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
torne-django@wolfpuppy.org.uk
Karen Tracey <graybark@bellsouth.net>
tstromberg@google.com
Makoto Tsuyuki <mtsuyuki@gmail.com>
tt@gurgle.no
Amit Upadhyay
@ -250,6 +289,7 @@ answer newbie questions, and generally made Django that much better:
charly.wilhelm@gmail.com
Rachel Willmer <http://www.willmer.com/kb/>
Gary Wilson <gary.wilson@gmail.com>
Jakub Wiśniowski <restless.being@gmail.com>
wojtek
ye7cakf02@sneakemail.com
ymasuda@ethercube.com

View File

@ -4,5 +4,6 @@ def get_version():
"Returns the version as a human-format string."
v = '.'.join([str(i) for i in VERSION[:-1]])
if VERSION[-1]:
v += '-' + VERSION[-1]
from django.utils.version import get_svn_revision
v = '%s-%s-%s' % (v, VERSION[-1], get_svn_revision())
return v

View File

@ -9,6 +9,7 @@ import re
import os
import sys
import getopt
from itertools import dropwhile
pythonize_re = re.compile(r'\n\s*//')
@ -83,7 +84,7 @@ def make_messages():
thefile = '%s.py' % file
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
@ -100,12 +101,13 @@ def make_messages():
thefile = file
if file.endswith('.html'):
src = open(os.path.join(dirpath, file), "rb").read()
open(os.path.join(dirpath, '%s.py' % file), "wb").write(templatize(src))
thefile = '%s.py' % file
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
open(os.path.join(dirpath, thefile), "wb").write(templatize(src))
if verbose:
sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
@ -116,13 +118,18 @@ def make_messages():
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
if thefile != file:
os.unlink(os.path.join(dirpath, thefile))
if os.path.exists(potfile):
(stdin, stdout, stderr) = os.popen3('msguniq "%s"' % potfile, 'b')
(stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:

View File

@ -37,6 +37,8 @@ class LazySettings(object):
# __setattr__(), which would be an infinite loop.
self.__dict__['_target'] = value
else:
if self._target is None:
self._import_settings()
setattr(self._target, name, value)
def _import_settings(self):

View File

@ -25,12 +25,12 @@ ADMINS = ()
INTERNAL_IPS = ()
# Local time zone for this installation. All choices can be found here:
# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name (although not all
# systems may support all possibilities).
TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here:
# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
# http://blogs.law.harvard.edu/tech/stories/storyReader$15
LANGUAGE_CODE = 'en-us'
# Languages we provide translations for, out of the box. The language name
@ -54,6 +54,7 @@ LANGUAGES = (
('gl', gettext_noop('Galician')),
('hu', gettext_noop('Hungarian')),
('he', gettext_noop('Hebrew')),
('hr', gettext_noop('Croatian')),
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
@ -81,7 +82,7 @@ LANGUAGES = (
)
# Languages using BiDi (right-to-left) layout
LANGUAGES_BIDI = ("he", "ar")
LANGUAGES_BIDI = ("he", "ar", "fa")
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
@ -97,6 +98,9 @@ MANAGERS = ADMINS
DEFAULT_CONTENT_TYPE = 'text/html'
DEFAULT_CHARSET = 'utf-8'
# Encoding of files read from disk (template and initial SQL files).
FILE_CHARSET = 'utf-8'
# E-mail address that error messages come from.
SERVER_EMAIL = 'root@localhost'
@ -280,6 +284,7 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user
# possible values.
CACHE_BACKEND = 'simple://'
CACHE_MIDDLEWARE_KEY_PREFIX = ''
CACHE_MIDDLEWARE_SECONDS = 600
####################
# COMMENTS #

View File

@ -237,7 +237,7 @@ msgstr "Coreà"
#: conf/global_settings.py:61
msgid "Kannada"
msgstr ""
msgstr "Canès"
#: conf/global_settings.py:62
msgid "Latvian"
@ -1230,7 +1230,7 @@ msgstr "Pot editar-lo de nou abaix."
#: contrib/admin/views/auth.py:30
msgid "Add user"
msgstr "Agregar usuari"
msgstr "Afegir usuari"
#: contrib/admin/views/auth.py:57
msgid "Password changed successfully."
@ -1248,12 +1248,12 @@ msgstr "Lloc administratiu"
#: contrib/admin/views/main.py:276 contrib/admin/views/main.py:361
#, python-format
msgid "You may add another %s below."
msgstr "Pot agregar un altre %s abaix."
msgstr "Pot afegir un altre %s a baix."
#: contrib/admin/views/main.py:294
#, python-format
msgid "Add %s"
msgstr "Agregar %s"
msgstr "Afegir %s"
#: contrib/admin/views/main.py:340
#, python-format

View File

@ -3,10 +3,10 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Django 1.0\n"
""
msgstr "Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-04-09 22:42+0200\n"
"POT-Creation-Date: 2007-07-28 12:33+0200\n"
"PO-Revision-Date: 2007-02-05 03:19+0100\n"
"Last-Translator: Jannis Leidel <jl@websushi.org>\n"
"Language-Team: \n"
@ -19,14 +19,18 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: KBabel 1.11.4\n"
#: conf/global_settings.py:39
#:conf/global_settings.py:38
msgid "Arabic"
msgstr "Arabisch"
#: conf/global_settings.py:40
#:conf/global_settings.py:39
msgid "Bengali"
msgstr "Bengali"
#:conf/global_settings.py:40
msgid "Bulgarian"
msgstr "Bulgarisch"
#:conf/global_settings.py:41
msgid "Catalan"
msgstr "Katalanisch"
@ -64,195 +68,198 @@ msgid "Argentinean Spanish"
msgstr "Argentinisches Spanisch"
#:conf/global_settings.py:50
msgid "Persian"
msgstr "Persisch"
#:conf/global_settings.py:51
msgid "Finnish"
msgstr "Finnisch"
#: conf/global_settings.py:51
#:conf/global_settings.py:52
msgid "French"
msgstr "Französisch"
#: conf/global_settings.py:52
#:conf/global_settings.py:53
msgid "Galician"
msgstr "Galicisch"
#: conf/global_settings.py:53
#:conf/global_settings.py:54
msgid "Hungarian"
msgstr "Ungarisch"
#: conf/global_settings.py:54
#:conf/global_settings.py:55
msgid "Hebrew"
msgstr "Hebräisch"
#: conf/global_settings.py:55
#:conf/global_settings.py:56
msgid "Icelandic"
msgstr "Isländisch"
#: conf/global_settings.py:56
#:conf/global_settings.py:57
msgid "Italian"
msgstr "Italienisch"
#: conf/global_settings.py:57
#:conf/global_settings.py:58
msgid "Japanese"
msgstr "Japanisch"
#: conf/global_settings.py:58
#:conf/global_settings.py:59
msgid "Korean"
msgstr "Koreanisch"
#: conf/global_settings.py:59
#:conf/global_settings.py:60
msgid "Kannada"
msgstr "Kannada"
#: conf/global_settings.py:60
#:conf/global_settings.py:61
msgid "Latvian"
msgstr "Lettisch"
#: conf/global_settings.py:61
#:conf/global_settings.py:62
msgid "Macedonian"
msgstr "Mazedonisch"
#: conf/global_settings.py:62
#:conf/global_settings.py:63
msgid "Dutch"
msgstr "Holländisch"
#: conf/global_settings.py:63
#:conf/global_settings.py:64
msgid "Norwegian"
msgstr "Norwegisch"
#: conf/global_settings.py:64
#:conf/global_settings.py:65
msgid "Polish"
msgstr "Polnisch"
#: conf/global_settings.py:65
#:conf/global_settings.py:66
msgid "Portugese"
msgstr "Portugiesisch"
#: conf/global_settings.py:66
#:conf/global_settings.py:67
msgid "Brazilian"
msgstr "Brasilianisches Portugiesisch"
#: conf/global_settings.py:67
#:conf/global_settings.py:68
msgid "Romanian"
msgstr "Rumänisch"
#: conf/global_settings.py:68
#:conf/global_settings.py:69
msgid "Russian"
msgstr "Russisch"
#: conf/global_settings.py:69
#:conf/global_settings.py:70
msgid "Slovak"
msgstr "Slowakisch"
#: conf/global_settings.py:70
#:conf/global_settings.py:71
msgid "Slovenian"
msgstr "Slowenisch"
#: conf/global_settings.py:71
#:conf/global_settings.py:72
msgid "Serbian"
msgstr "Serbisch"
#: conf/global_settings.py:72
#:conf/global_settings.py:73
msgid "Swedish"
msgstr "Schwedisch"
#: conf/global_settings.py:73
#:conf/global_settings.py:74
msgid "Tamil"
msgstr "Tamilisch"
#: conf/global_settings.py:74
#:conf/global_settings.py:75
msgid "Telugu"
msgstr "Telugisch"
#: conf/global_settings.py:75
#:conf/global_settings.py:76
msgid "Turkish"
msgstr "Türkisch"
#: conf/global_settings.py:76
#:conf/global_settings.py:77
msgid "Ukrainian"
msgstr "Ukrainisch"
#: conf/global_settings.py:77
#:conf/global_settings.py:78
msgid "Simplified Chinese"
msgstr "Vereinfachtes Chinesisch"
#: conf/global_settings.py:78
#:conf/global_settings.py:79
msgid "Traditional Chinese"
msgstr "Traditionelles Chinesisch"
#: contrib/admin/filterspecs.py:40
#:contrib/admin/filterspecs.py:42
#,python-format
msgid ""
"<h3>By %s:</h3>\n"
"<ul>\n"
msgstr ""
"<h3>Nach %s:</h3>\n"
msgstr "<h3>Nach %s:</h3>\n"
"<ul>\n"
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169
#:contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90
#:contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171
msgid "All"
msgstr "Alle"
#: contrib/admin/filterspecs.py:109
#:contrib/admin/filterspecs.py:111
msgid "Any date"
msgstr "Alle Daten"
#: contrib/admin/filterspecs.py:110
#:contrib/admin/filterspecs.py:112
msgid "Today"
msgstr "Heute"
#: contrib/admin/filterspecs.py:113
#:contrib/admin/filterspecs.py:115
msgid "Past 7 days"
msgstr "Letzte 7 Tage"
#: contrib/admin/filterspecs.py:115
#:contrib/admin/filterspecs.py:117
msgid "This month"
msgstr "Diesen Monat"
#: contrib/admin/filterspecs.py:117
#:contrib/admin/filterspecs.py:119
msgid "This year"
msgstr "Dieses Jahr"
#: contrib/admin/filterspecs.py:143 newforms/widgets.py:180
#: oldforms/__init__.py:577
#:contrib/admin/filterspecs.py:145 newforms/widgets.py:181
#:oldforms/__init__.py:587
msgid "Yes"
msgstr "Ja"
#: contrib/admin/filterspecs.py:143 newforms/widgets.py:180
#: oldforms/__init__.py:577
#:contrib/admin/filterspecs.py:145 newforms/widgets.py:181
#:oldforms/__init__.py:587
msgid "No"
msgstr "Nein"
#: contrib/admin/filterspecs.py:150 newforms/widgets.py:180
#: oldforms/__init__.py:577
#:contrib/admin/filterspecs.py:152 newforms/widgets.py:181
#:oldforms/__init__.py:587
msgid "Unknown"
msgstr "Unbekannt"
#: contrib/admin/models.py:16
#:contrib/admin/models.py:17
msgid "action time"
msgstr "Zeitpunkt der Aktion"
#: contrib/admin/models.py:19
#:contrib/admin/models.py:20
msgid "object id"
msgstr "Objekt-ID"
#: contrib/admin/models.py:20
#:contrib/admin/models.py:21
msgid "object repr"
msgstr "Objekt Darst."
#: contrib/admin/models.py:21
#:contrib/admin/models.py:22
msgid "action flag"
msgstr "Aktionskennzeichen"
#: contrib/admin/models.py:22
#:contrib/admin/models.py:23
msgid "change message"
msgstr "Änderungsmeldung"
#: contrib/admin/models.py:25
#:contrib/admin/models.py:26
msgid "log entry"
msgstr "Logeintrag"
#: contrib/admin/models.py:26
#:contrib/admin/models.py:27
msgid "log entries"
msgstr "Logeinträge"
@ -263,8 +270,7 @@ msgstr "Seite nicht gefunden"
#:contrib/admin/templates/admin/404.html:10
msgid "We're sorry, but the requested page could not be found."
msgstr ""
"Es tut uns leid, aber die angeforderte Seite konnte nicht gefunden werden."
msgstr "Es tut uns leid, aber die angeforderte Seite konnte nicht gefunden werden."
#:contrib/admin/templates/admin/500.html:4
#:contrib/admin/templates/admin/base.html:30
@ -299,8 +305,7 @@ msgstr "Serverfehler <em>(500)</em>"
msgid ""
"There's been an error. It's been reported to the site administrators via e-"
"mail and should be fixed shortly. Thanks for your patience."
msgstr ""
"Ein Fehler ist aufgetreten. Dieser Fehler wurde an die Serververwalter per E-"
msgstr "Ein Fehler ist aufgetreten. Dieser Fehler wurde an die Serververwalter per E-"
"Mail weitergegeben und sollte bald behoben sein. Vielen Dank für Ihr "
"Verständnis."
@ -418,8 +423,7 @@ msgid ""
"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
"related objects, but your account doesn't have permission to delete the "
"following types of objects:"
msgstr ""
"Die Löschung des %(object_name)s '%(escaped_object)s' hätte die Löschung von "
msgstr "Die Löschung des %(object_name)s '%(escaped_object)s' hätte die Löschung von "
"abhängigen Daten zur Folge, aber Sie haben nicht die nötigen Rechte um die "
"folgenden abhängigen Daten zu löschen:"
@ -428,8 +432,7 @@ msgstr ""
msgid ""
"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
"All of the following related items will be deleted:"
msgstr ""
"Sind Sie sicher, dass Sie %(object_name)s \"%(escaped_object)s\" löschen "
msgstr "Sind Sie sicher, dass Sie %(object_name)s \"%(escaped_object)s\" löschen "
"wollen? Es werden zusätzlich die folgenden abhängigen Daten mit gelöscht:"
#:contrib/admin/templates/admin/delete_confirmation.html:26
@ -480,10 +483,9 @@ 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 ""
"Etwas stimmt nicht mit der Datenbankkonfiguration. Bitte sicherstellen, dass "
"die richtigen Datenbanktabellen angelegt wurden und "
"die Datenbank vom verwendeten Datenbankbenutzer auch lesbar ist."
msgstr "Etwas stimmt nicht mit der Datenbankkonfiguration. Bitte sicherstellen, dass "
"die richtigen Datenbanktabellen angelegt wurden und die Datenbank vom "
"verwendeten Datenbankbenutzer auch lesbar ist."
#:contrib/admin/templates/admin/login.html:17
#:contrib/comments/templates/comments/form.html:6
@ -521,8 +523,7 @@ msgstr "j. N Y, H:i"
msgid ""
"This object doesn't have a change history. It probably wasn't added via this "
"admin site."
msgstr ""
"Dieses Objekt hat keine Änderungsgeschichte. Es wurde möglicherweise nicht "
msgstr "Dieses Objekt hat keine Änderungsgeschichte. Es wurde möglicherweise nicht "
"über diese Verwaltungsseiten angelegt."
#:contrib/admin/templates/admin/pagination.html:10
@ -565,8 +566,7 @@ msgstr "Sichern"
msgid ""
"First, enter a username and password. Then, you'll be able to edit more user "
"options."
msgstr ""
"Zuerst einen Benutzer und ein Passwort eingeben. Danach können weitere "
msgstr "Zuerst einen Benutzer und ein Passwort eingeben. Danach können weitere "
"Optionen für den Benutzer geändert werden."
#:contrib/admin/templates/admin/auth/user/add_form.html:12
@ -591,8 +591,7 @@ msgstr "Bitte das gleiche Passwort zur Überprüfung nochmal eingeben."
#:contrib/admin/templates/admin/auth/user/change_password.html:28
#,python-format
msgid "Enter a new password for the user <strong>%(username)s</strong>."
msgstr ""
"Bitte geben Sie ein neues Passwort für den Benutzer <strong>%(username)s</"
msgstr "Bitte geben Sie ein neues Passwort für den Benutzer <strong>%(username)s</"
"strong> ein."
#:contrib/admin/templates/admin_doc/bookmarklets.html:3
@ -612,9 +611,9 @@ msgid ""
"bookmarklets require you to be viewing the site from a computer designated\n"
"as \"internal\" (talk to your system administrator if you aren't sure if\n"
"your computer is \"internal\").</p>\n"
msgstr ""
"\n"
"<p class=\"help\">Um Bookmarklets zu installieren, müssen diese Links in die\n"
msgstr "\n"
"<p class=\"help\">Um Bookmarklets zu installieren, müssen diese Links in "
"die\n"
"Browser-Werkzeugleiste gezogen werden, oder mittels rechter Maustaste in "
"die\n"
"Bookmarks gespeichert werden. Danach können die Bookmarklets von jeder "
@ -830,7 +829,7 @@ msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
msgstr ""
"Bitte einen Benutzernamen und ein Passwort eingeben. Beide Felder "
"Bitte einen gültigen Benutzernamen und ein Passwort eingeben. Beide Felder "
"berücksichtigen die Groß-/Kleinschreibung."
#: contrib/admin/views/decorators.py:62

View File

@ -11,21 +11,21 @@ msgstr ""
"PO-Revision-Date: 2005-12-04 13:21+0100\n"
"Last-Translator: Dirk Eschler <dirk.eschler@gmx.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Verfügbare %s"
msgstr "Verfügbare %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Alles auswählen"
msgstr "Alles auswählen"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Hinzufügen"
msgstr "Hinzufügen"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
@ -34,15 +34,15 @@ msgstr "Entfernen"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Ausgewählte %s"
msgstr "Ausgewählte %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Gewünschte Auswahl treffen und "
msgstr "Gewünschte Auswahl treffen und "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Alles abwählen"
msgstr "Alles abwählen"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
@ -50,7 +50,7 @@ msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Januar Februar März April Mai Juni Juli August September Oktober November "
"Januar Februar März April Mai Juni Juli August September Oktober November "
"Dezember"
#: contrib/admin/media/js/dateparse.js:27

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,41 @@
# Spanish translation for the django-admin JS files.
# Copyright (C)
# This file is distributed under the same license as the PACKAGE package.
# Jorge Gajon <gajon@gajon.org>, 2005.
#
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"
"PO-Revision-Date: 2005-12-06 21:32+0100\n"
"POT-Creation-Date: 2007-07-14 13:47-0500\n"
"PO-Revision-Date: 2007-07-14 13:41-0500\n"
"Last-Translator: Jorge Gajon <gajon@gajon.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/calendar.js:24
#: contrib/admin/media/js/dateparse.js:32
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre "
"Noviembre Diciembre"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "D L M M J V S"
#: 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"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "%s Disponibles"
#: contrib/admin/media/js/SelectFilter2.js:41
#, fuzzy
msgid "Choose all"
msgstr "Selecciona todos"
@ -45,66 +60,58 @@ msgstr "Haz tus elecciones y da click en "
msgid "Clear all"
msgstr "Elimina todos"
#: 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 ""
"Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre "
"Noviembre Diciembre"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Domingo Lunes Martes Miércoles Jueves Viernes Sábado"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "D L M M J V S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "Ahora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "Reloj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Elige una hora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Medianoche"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Mediodía"
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:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
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:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Hoy"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Calendario"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Ayer"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Mañana"
msgstr "Mañana"
#: 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 "Esconder"

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
# Argentinean spanish translation for the django-admin JS files, based on
# Spanish translation work by Jorge Gajon.
# This file is distributed under the same license as the Django package.
# Copyright (C) Ramiro Morales <rm0@gmx.net>, 2006,2007.
# 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 JavaScript 1.0\n"
"Project-Id-Version: Django Javascript 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-02-25 17:48-0300\n"
"PO-Revision-Date: 2007-02-25 17:55-0300\n"
"POT-Creation-Date: 2007-07-14 13:45-0300\n"
"PO-Revision-Date: 2007-07-14 14:36-0300\n"
"Last-Translator: Ramiro Morales <rm0@gmx.net>\n"
"Language-Team: Django-I18N <django-i18n@googlegroups.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
@ -55,7 +55,7 @@ msgstr ""
#: 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"
msgstr "Domingo Lunes Martes Miércoles Jueves Viernes Sábado"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
@ -93,7 +93,7 @@ msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Mediodía"
msgstr "Mediodía"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
@ -115,4 +115,4 @@ msgstr "Ayer"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Mañana"
msgstr "Mañana"

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# French translation for js.
# Copyright (C) 2005 Mikaël Barbero
# Copyright (C) 2005 Mikaël Barbero
# This file is distributed under the same license as the PACKAGE package.
# Mikaël Barbero <mikael.barbero nospam at nospam free.fr>, 2005.
# Mikaël Barbero <mikael.barbero nospam at nospam free.fr>, 2005.
#
msgid ""
msgstr ""
@ -9,10 +9,10 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-24 16:39+0100\n"
"PO-Revision-Date: 2005-12-24 16:39+0100\n"
"Last-Translator: Mikaël Barbero <mikael.barbero nospam at nospam free.fr>\n"
"Last-Translator: Mikaël Barbero <mikael.barbero nospam at nospam free.fr>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/calendar.js:24
@ -21,8 +21,8 @@ msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre "
"Décembre"
"Janvier Février Mars Avril Mai Juin Juillet Août Septembre Octobre Novembre "
"Décembre"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
@ -35,7 +35,7 @@ msgstr "Dimanche Lundi Mardi Mercredi Jeudi Vendredi Samedi"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Disponible %s"
msgstr "%s disponible(s)"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
@ -52,11 +52,11 @@ msgstr "Enlever"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Choisi %s"
msgstr "%s choisi(es)"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Sélectionnez un ou plusieurs choix et cliquez "
msgstr "Sélectionnez un ou plusieurs choix et cliquez "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,118 @@
# 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: 2007-08-13 11:13+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\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
#, perl-format
msgid "Available %s"
msgstr ""
#: 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 ""
#: 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:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr ""
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr ""
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@ msgstr "Domenica Lunedì Martedì Mercoledì Giovedì Venerdì Sabato"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Disponibile %s"
msgstr "%s disponibili"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
@ -55,11 +55,11 @@ msgstr "Rimuovi"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Scelto %s"
msgstr "%s scelti"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Seleziona le tue scelte e clicca "
msgstr "Fai le tue scelte e clicca "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@ msgid ""
msgstr ""
"Project-Id-Version: DJANGO-JS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2007-03-31 21:29+0100\n"
"POT-Creation-Date: 2007-07-02 13:55+0200\n"
"PO-Revision-Date: 2007-07-02 13:56+0100\n"
"Last-Translator: Gasper Koren <skrat@owca.info>\n"
"Language-Team: SLOVENIAN <lugos-slo@lugos.si>\n"
"MIME-Version: 1.0\n"
@ -15,6 +15,19 @@ msgstr ""
"X-Poedit-Language: Slovenian\n"
"X-Poedit-Country: SLOVENIA\n"
#: contrib/admin/media/js/calendar.js:24
#: contrib/admin/media/js/dateparse.js:32
msgid "January February March April May June July August September October November December"
msgstr "Januar Februar Marec April Maj Junij Julij Avgust September Oktober November December"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "N P T S Č P S"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Nedelja Ponedeljek Torek Sreda Četrtek Petek Sobota"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
@ -45,63 +58,59 @@ msgstr "Izberite in kliknite"
msgid "Clear all"
msgstr "Izbriši vse"
#: 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 "Januar Februar Marec April Maj Junij Julij Avgust September Oktober November December"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Nedelja Ponedeljek Torek Sreda Četrtek Petek Sobota"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "N P T S Č P S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "Sedaj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "URA"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Izberite čas"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Polnoč"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "Ob 6h"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Opoldne"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "Prekliči"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Danes"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Koledar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Včeraj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Jutri"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "Prikaži"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "Skrij"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,15 +17,14 @@ DATABASE_HOST = '' # Set to empty string for localhost. Not used wit
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
# Local time zone for this installation. Choices can be found here:
# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
# although not all variations may be possible on all operating systems.
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be avilable on all operating systems.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here:
# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
# http://blogs.law.harvard.edu/tech/stories/storyReader$15
LANGUAGE_CODE = 'en-us'
SITE_ID = 1

View File

@ -7,6 +7,8 @@ certain test -- e.g. being a DateField or ForeignKey.
"""
from django.db import models
from django.utils.encoding import smart_unicode, iri_to_uri
from django.utils.translation import ugettext as _
import datetime
class FilterSpec(object):
@ -37,12 +39,12 @@ class FilterSpec(object):
def output(self, cl):
t = []
if self.has_output():
t.append(_('<h3>By %s:</h3>\n<ul>\n') % self.title())
t.append(_(u'<h3>By %s:</h3>\n<ul>\n') % self.title())
for choice in self.choices(cl):
t.append('<li%s><a href="%s">%s</a></li>\n' % \
t.append(u'<li%s><a href="%s">%s</a></li>\n' % \
((choice['selected'] and ' class="selected"' or ''),
choice['query_string'] ,
iri_to_uri(choice['query_string']),
choice['display']))
t.append('</ul>\n\n')
return "".join(t)
@ -70,7 +72,7 @@ class RelatedFilterSpec(FilterSpec):
'display': _('All')}
for val in self.lookup_choices:
pk_val = getattr(val, self.field.rel.to._meta.pk.attname)
yield {'selected': self.lookup_val == str(pk_val),
yield {'selected': self.lookup_val == smart_unicode(pk_val),
'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}),
'display': val}
@ -87,7 +89,7 @@ class ChoicesFilterSpec(FilterSpec):
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': _('All')}
for k, v in self.field.choices:
yield {'selected': str(k) == self.lookup_val,
yield {'selected': smart_unicode(k) == self.lookup_val,
'query_string': cl.get_query_string({self.lookup_kwarg: k}),
'display': v}
@ -168,7 +170,7 @@ class AllValuesFilterSpec(FilterSpec):
'query_string': cl.get_query_string({}, [self.field.name]),
'display': _('All')}
for val in self.lookup_choices:
val = str(val[self.field.name])
val = smart_unicode(val[self.field.name])
yield {'selected': self.lookup_val == val,
'query_string': cl.get_query_string({self.field.name: val}),
'display': val}

View File

@ -31,10 +31,11 @@ function showAddAnotherPopup(triggeringLink) {
var name = triggeringLink.id.replace(/^add_/, '');
name = name.replace(/\./g, '___');
href = triggeringLink.href
if (href.indexOf('?') == -1)
if (href.indexOf('?') == -1) {
href += '?_popup=1';
else
} else {
href += '&_popup=1';
}
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;

View File

@ -1,15 +1,121 @@
var LATIN_MAP = {
'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'o', 'ñ': 'n', 'ò': 'o', 'ó':
'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
}
var LATIN_SYMBOLS_MAP = {
'©':'(c)'
}
var GREEK_MAP = {
'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
'Ϋ':'Y'
}
var TURKISH_MAP = {
'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
}
var RUSSIAN_MAP = {
'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
'я':'ya',
'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
'Я':'Ya'
}
var CZECH_MAP = {
'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
'ž':'z'
}
var ALL_DOWNCODE_MAPS=new Array()
ALL_DOWNCODE_MAPS[0]=LATIN_MAP
ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
ALL_DOWNCODE_MAPS[2]=GREEK_MAP
ALL_DOWNCODE_MAPS[3]=TURKISH_MAP
ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP
ALL_DOWNCODE_MAPS[5]=CZECH_MAP
var Downcoder = new Object();
Downcoder.Initialize = function()
{
if (Downcoder.map) // already made
return ;
Downcoder.map ={}
Downcoder.chars = '' ;
for(var i in ALL_DOWNCODE_MAPS)
{
var lookup = ALL_DOWNCODE_MAPS[i]
for (var c in lookup)
{
Downcoder.map[c] = lookup[c] ;
Downcoder.chars += c ;
}
}
Downcoder.regex = new RegExp('[' + Downcoder.chars + ']|[^' + Downcoder.chars + ']+','g') ;
}
downcode= function( slug )
{
Downcoder.Initialize() ;
var downcoded =""
var pieces = slug.match(Downcoder.regex);
if(pieces)
{
for (var i = 0 ; i < pieces.length ; i++)
{
if (pieces[i].length == 1)
{
var mapped = Downcoder.map[pieces[i]] ;
if (mapped != null)
{
downcoded+=mapped;
continue ;
}
}
downcoded+=pieces[i];
}
}
else
{
downcoded = slug;
}
return downcoded;
}
function URLify(s, num_chars) {
// changes, e.g., "Petty theft" to "petty_theft"
// remove all these words from the string before urlifying
s = downcode(s);
removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
"is", "in", "into", "like", "of", "off", "on", "onto", "per",
"since", "than", "the", "this", "that", "to", "up", "via",
"with"];
r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
s = s.replace(r, '');
// if downcode doesn't hit, the char will be stripped here
s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
s = s.toLowerCase(); // convert to lowercase
return s.substring(0, num_chars);// trim to first num_chars chars
}

View File

@ -1,7 +1,8 @@
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
ADDITION = 1
CHANGE = 2
@ -9,7 +10,7 @@ DELETION = 3
class LogEntryManager(models.Manager):
def log_action(self, user_id, content_type_id, object_id, object_repr, action_flag, change_message=''):
e = self.model(None, None, user_id, content_type_id, str(object_id), object_repr[:200], action_flag, change_message)
e = self.model(None, None, user_id, content_type_id, smart_unicode(object_id), object_repr[:200], action_flag, change_message)
e.save()
class LogEntry(models.Model):
@ -17,7 +18,7 @@ class LogEntry(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType, blank=True, null=True)
object_id = models.TextField(_('object id'), blank=True, null=True)
object_repr = models.CharField(_('object repr'), maxlength=200)
object_repr = models.CharField(_('object repr'), max_length=200)
action_flag = models.PositiveSmallIntegerField(_('action flag'))
change_message = models.TextField(_('change message'), blank=True)
objects = LogEntryManager()
@ -28,7 +29,7 @@ class LogEntry(models.Model):
ordering = ('-action_time',)
def __repr__(self):
return str(self.action_time)
return smart_unicode(self.action_time)
def is_addition(self):
return self.action_flag == ADDITION
@ -48,4 +49,4 @@ class LogEntry(models.Model):
Returns the admin URL to edit the object represented by this log entry.
This is relative to the Django admin index page.
"""
return "%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, self.object_id)
return u"%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, self.object_id)

View File

@ -6,7 +6,7 @@
{% endblock %}
{% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %}
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% 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 %}
{% 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 %}{% if not is_popup %}
<div class="breadcrumbs">
<a href="../../../../">{% trans "Home" %}</a> &rsaquo;

View File

@ -3,6 +3,6 @@
<ul>
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
<a href="{{ choice.query_string }}">{{ choice.display|escape }}</a></li>
<a href="{{ choice.query_string|iriencode }}">{{ choice.display|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -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|escape }}</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">{% filter capfirst|escape %}{% trans entry.content_type.name %}{% endfilter %}</span></li>
{% endfor %}
</ul>
{% endif %}

View File

@ -6,7 +6,8 @@ from django.db import models
from django.utils import dateformat
from django.utils.html import escape
from django.utils.text import capfirst
from django.utils.translation import get_date_formats, get_partial_date_formats
from django.utils.translation import get_date_formats, get_partial_date_formats, ugettext as _
from django.utils.encoding import smart_unicode, smart_str, force_unicode
from django.template import Library
import datetime
@ -16,11 +17,11 @@ DOT = '.'
def paginator_number(cl,i):
if i == DOT:
return '... '
return u'... '
elif i == cl.page_num:
return '<span class="this-page">%d</span> ' % (i+1)
return u'<span class="this-page">%d</span> ' % (i+1)
else:
return '<a href="%s"%s>%d</a> ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class="end"' or ''), i+1)
return u'<a href="%s"%s>%d</a> ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class="end"' or ''), i+1)
paginator_number = register.simple_tag(paginator_number)
def pagination(cl):
@ -75,10 +76,12 @@ def result_headers(cl):
admin_order_field = None
except models.FieldDoesNotExist:
# For non-field list_display values, check for the function
# attribute "short_description". If that doesn't exist, fall
# back to the method name. And __str__ is a special-case.
if field_name == '__str__':
header = lookup_opts.verbose_name
# attribute "short_description". If that doesn't exist, fall back
# to the method name. And __str__ and __unicode__ are special-cases.
if field_name == '__unicode__':
header = force_unicode(lookup_opts.verbose_name)
elif field_name == '__str__':
header = smart_str(lookup_opts.verbose_name)
else:
attr = getattr(cl.model, field_name) # Let AttributeErrors propagate.
try:
@ -114,7 +117,7 @@ def result_headers(cl):
def _boolean_icon(field_val):
BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}
return '<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
return u'<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
def items_for_result(cl, result):
first = True
@ -136,7 +139,7 @@ def items_for_result(cl, result):
allow_tags = True
result_repr = _boolean_icon(attr)
else:
result_repr = str(attr)
result_repr = smart_unicode(attr)
except (AttributeError, ObjectDoesNotExist):
result_repr = EMPTY_CHANGELIST_VALUE
else:
@ -179,19 +182,21 @@ def items_for_result(cl, result):
elif f.choices:
result_repr = dict(f.choices).get(field_val, EMPTY_CHANGELIST_VALUE)
else:
result_repr = escape(str(field_val))
if result_repr == '':
result_repr = escape(field_val)
if force_unicode(result_repr) == '':
result_repr = '&nbsp;'
# 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 ('<%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))
# Convert the pk to something that can be used in Javascript.
# Problem cases are long ints (23L) and non-ASCII strings.
result_id = repr(force_unicode(getattr(result, pk)))[1:]
yield (u'<%s%s><a href="%s"%s>%s</a></%s>' % \
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), result_repr, table_tag))
else:
yield ('<td%s>%s</td>' % (row_class, result_repr))
yield (u'<td%s>%s</td>' % (row_class, result_repr))
def results(cl):
for res in cl.result_list:

View File

@ -2,6 +2,7 @@ from django import template
from django.contrib.admin.views.main import AdminBoundField
from django.template import loader
from django.utils.text import capfirst
from django.utils.encoding import force_unicode
from django.db import models
from django.db.models.fields import Field
from django.db.models.related import BoundRelatedObject
@ -14,7 +15,7 @@ word_re = re.compile('[A-Z][a-z]+')
absolute_url_re = re.compile(r'^(?:http(?:s)?:/)?/', re.IGNORECASE)
def class_name_to_underscored(name):
return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
return u'_'.join([s.lower() for s in word_re.findall(name)[:-1]])
def include_admin_script(script_path):
"""
@ -31,7 +32,7 @@ def include_admin_script(script_path):
"""
if not absolute_url_re.match(script_path):
script_path = '%s%s' % (settings.ADMIN_MEDIA_PREFIX, script_path)
return '<script type="text/javascript" src="%s"></script>' % script_path
return u'<script type="text/javascript" src="%s"></script>' % script_path
include_admin_script = register.simple_tag(include_admin_script)
def submit_row(context):
@ -61,9 +62,9 @@ def field_label(bound_field):
if not bound_field.first:
class_names.append('inline')
colon = ":"
class_str = class_names and ' class="%s"' % ' '.join(class_names) or ''
return '<label for="%s"%s>%s%s</label> ' % (bound_field.element_id, class_str, \
capfirst(bound_field.field.verbose_name), colon)
class_str = class_names and u' class="%s"' % u' '.join(class_names) or u''
return u'<label for="%s"%s>%s%s</label> ' % (bound_field.element_id, class_str, \
force_unicode(capfirst(bound_field.field.verbose_name)), colon)
field_label = register.simple_tag(field_label)
class FieldWidgetNode(template.Node):
@ -77,7 +78,7 @@ class FieldWidgetNode(template.Node):
if klass not in cls.nodelists:
try:
field_class_name = klass.__name__
template_name = "widget/%s.html" % class_name_to_underscored(field_class_name)
template_name = u"widget/%s.html" % class_name_to_underscored(field_class_name)
nodelist = loader.get_template(template_name).nodelist
except template.TemplateDoesNotExist:
super_klass = bool(klass.__bases__) and klass.__bases__[0] or None
@ -175,30 +176,30 @@ class EditInlineNode(template.Node):
return output
def output_all(form_fields):
return ''.join([str(f) for f in form_fields])
return u''.join([force_unicode(f) for f in form_fields])
output_all = register.simple_tag(output_all)
def auto_populated_field_script(auto_pop_fields, change = False):
t = []
for field in auto_pop_fields:
if change:
t.append('document.getElementById("id_%s")._changed = true;' % field.name)
t.append(u'document.getElementById("id_%s")._changed = true;' % field.name)
else:
t.append('document.getElementById("id_%s").onchange = function() { this._changed = true; };' % field.name)
t.append(u'document.getElementById("id_%s").onchange = function() { this._changed = true; };' % field.name)
add_values = ' + " " + '.join(['document.getElementById("id_%s").value' % g for g in field.prepopulate_from])
add_values = u' + " " + '.join([u'document.getElementById("id_%s").value' % g for g in field.prepopulate_from])
for f in field.prepopulate_from:
t.append('document.getElementById("id_%s").onkeyup = function() {' \
t.append(u'document.getElementById("id_%s").onkeyup = function() {' \
' var e = document.getElementById("id_%s");' \
' if(!e._changed) { e.value = URLify(%s, %s);} }; ' % (
f, field.name, add_values, field.maxlength))
return ''.join(t)
f, field.name, add_values, field.max_length))
return u''.join(t)
auto_populated_field_script = register.simple_tag(auto_populated_field_script)
def filter_interface_script_maybe(bound_field):
f = bound_field.field
if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface:
return '<script type="text/javascript">addEvent(window, "load", function(e) {' \
return u'<script type="text/javascript">addEvent(window, "load", function(e) {' \
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
f.name, f.verbose_name.replace('"', '\\"'), f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
else:

View File

@ -1,5 +1,6 @@
from django import template
from django.db.models import get_models
from django.utils.encoding import force_unicode
register = template.Library()
@ -36,8 +37,8 @@ class AdminApplistNode(template.Node):
# If so, add the module to the model_list.
if True in perms.values():
model_list.append({
'name': capfirst(m._meta.verbose_name_plural),
'admin_url': '%s/%s/' % (app_label, m.__name__.lower()),
'name': force_unicode(capfirst(m._meta.verbose_name_plural)),
'admin_url': u'%s/%s/' % (force_unicode(app_label), m.__name__.lower()),
'perms': perms,
})

View File

@ -6,6 +6,7 @@ from django import oldforms, template
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponseRedirect
from django.utils.html import escape
from django.utils.translation import ugettext as _
def user_add_stage(request):
if not request.user.has_perm('auth.change_user'):

View File

@ -3,11 +3,11 @@ from django.conf import settings
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
from django.utils.translation import ugettext_lazy, ugettext as _
import base64, datetime, md5
import cPickle as pickle
ERROR_MESSAGE = gettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
LOGIN_FORM_KEY = 'this_is_the_login_form'
def _display_login_form(request, error_message=''):

View File

@ -9,6 +9,7 @@ from django.http import Http404, get_host
from django.core import urlresolvers
from django.contrib.admin import utils
from django.contrib.sites.models import Site
from django.utils.translation import ugettext as _
import inspect, os, re
# Exclude methods starting with these strings from documentation
@ -290,7 +291,7 @@ def get_return_data_type(func_name):
DATA_TYPE_MAPPING = {
'AutoField' : _('Integer'),
'BooleanField' : _('Boolean (Either True or False)'),
'CharField' : _('String (up to %(maxlength)s)'),
'CharField' : _('String (up to %(max_length)s)'),
'CommaSeparatedIntegerField': _('Comma-separated integers'),
'DateField' : _('Date (without time)'),
'DateTimeField' : _('Date (with time)'),
@ -309,7 +310,7 @@ DATA_TYPE_MAPPING = {
'PhoneNumberField' : _('Phone number'),
'PositiveIntegerField' : _('Integer'),
'PositiveSmallIntegerField' : _('Integer'),
'SlugField' : _('String (up to %(maxlength)s)'),
'SlugField' : _('String (up to %(max_length)s)'),
'SmallIntegerField' : _('Integer'),
'TextField' : _('Text'),
'TimeField' : _('Time'),

View File

@ -12,6 +12,8 @@ from django.db.models.query import handle_legacy_orderlist, QuerySet
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.utils.html import escape
from django.utils.text import capfirst, get_text_list
from django.utils.encoding import force_unicode, smart_str
from django.utils.translation import ugettext as _
import operator
try:
@ -130,11 +132,11 @@ class AdminBoundField(object):
if max([bool(f.errors()) for f in self.form_fields]):
classes.append('error')
if classes:
self.cell_class_attribute = ' class="%s" ' % ' '.join(classes)
self.cell_class_attribute = u' class="%s" ' % ' '.join(classes)
self._repr_filled = False
if field.rel:
self.related_url = '../../../%s/%s/' % (field.rel.to._meta.app_label, field.rel.to._meta.object_name.lower())
self.related_url = u'../../../%s/%s/' % (field.rel.to._meta.app_label, field.rel.to._meta.object_name.lower())
def original_value(self):
if self.original:
@ -145,9 +147,9 @@ class AdminBoundField(object):
return self._display
except AttributeError:
if isinstance(self.field.rel, models.ManyToOneRel):
self._display = getattr(self.original, self.field.name)
self._display = force_unicode(getattr(self.original, self.field.name), strings_only=True)
elif isinstance(self.field.rel, models.ManyToManyRel):
self._display = ", ".join([str(obj) for obj in getattr(self.original, self.field.name).all()])
self._display = u", ".join([force_unicode(obj) for obj in getattr(self.original, self.field.name).all()])
return self._display
def __repr__(self):
@ -258,8 +260,8 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
if not errors:
new_object = manipulator.save(new_data)
pk_value = new_object._get_pk_val()
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), ADDITION)
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), ADDITION)
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(new_object)}
# Here, we distinguish between different save types by checking for
# the presence of keys in request.POST.
if "_continue" in request.POST:
@ -271,9 +273,9 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable.
pk_value = '"%s"' % pk_value.replace('"', '\\"')
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
(pk_value, str(new_object).replace('"', '\\"')))
(pk_value, force_unicode(new_object).replace('"', '\\"')))
elif "_addanother" in request.POST:
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
return HttpResponseRedirect(request.path)
else:
request.user.message_set.create(message=msg)
@ -291,7 +293,7 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
form = oldforms.FormWrapper(manipulator, new_data, errors)
c = template.RequestContext(request, {
'title': _('Add %s') % opts.verbose_name,
'title': _('Add %s') % force_unicode(opts.verbose_name),
'form': form,
'is_popup': '_popup' in request.REQUEST,
'show_delete': show_delete,
@ -345,9 +347,9 @@ def change_stage(request, app_label, model_name, object_id):
change_message = ' '.join(change_message)
if not change_message:
change_message = _('No fields changed.')
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), CHANGE, change_message)
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), CHANGE, change_message)
msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object}
msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(new_object)}
if "_continue" in request.POST:
request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
if '_popup' in request.REQUEST:
@ -355,10 +357,10 @@ def change_stage(request, app_label, model_name, object_id):
else:
return HttpResponseRedirect(request.path)
elif "_saveasnew" in request.POST:
request.user.message_set.create(message=_('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': opts.verbose_name, 'obj': new_object})
request.user.message_set.create(message=_('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(new_object)})
return HttpResponseRedirect("../%s/" % pk_value)
elif "_addanother" in request.POST:
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
return HttpResponseRedirect("../add/")
else:
request.user.message_set.create(message=msg)
@ -393,7 +395,7 @@ def change_stage(request, app_label, model_name, object_id):
form.order_objects.extend(orig_list)
c = template.RequestContext(request, {
'title': _('Change %s') % opts.verbose_name,
'title': _('Change %s') % force_unicode(opts.verbose_name),
'form': form,
'object_id': object_id,
'original': manipulator.original_object,
@ -434,11 +436,11 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
if related.field.rel.edit_inline or not related.opts.admin:
# Don't display link to edit, because it either has no
# admin or is edited inline.
nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), sub_obj), []])
nh(deleted_objects, current_depth, [u'%s: %s' % (force_unicode(capfirst(related.opts.verbose_name)), sub_obj), []])
else:
# Display a link to the admin page.
nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
(capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(),
nh(deleted_objects, current_depth, [u'%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
(force_unicode(capfirst(related.opts.verbose_name)), related.opts.app_label, related.opts.object_name.lower(),
sub_obj._get_pk_val(), sub_obj), []])
_get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
else:
@ -448,11 +450,11 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
if related.field.rel.edit_inline or not related.opts.admin:
# Don't display link to edit, because it either has no
# admin or is edited inline.
nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), escape(str(sub_obj))), []])
nh(deleted_objects, current_depth, [u'%s: %s' % (force_unicode(capfirst(related.opts.verbose_name)), escape(sub_obj)), []])
else:
# Display a link to the admin page.
nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
(capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(str(sub_obj))), []])
nh(deleted_objects, current_depth, [u'%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
(force_unicode(capfirst(related.opts.verbose_name)), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(sub_obj)), []])
_get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
# If there were related objects, and the user doesn't have
# permission to delete them, add the missing perm to perms_needed.
@ -479,17 +481,17 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
# Don't display link to edit, because it either has no
# admin or is edited inline.
nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \
{'fieldname': related.field.verbose_name, 'name': related.opts.verbose_name, 'obj': escape(str(sub_obj))}, []])
{'fieldname': force_unicode(related.field.verbose_name), 'name': force_unicode(related.opts.verbose_name), 'obj': escape(sub_obj)}, []])
else:
# Display a link to the admin page.
nh(deleted_objects, current_depth, [
(_('One or more %(fieldname)s in %(name)s:') % {'fieldname': related.field.verbose_name, 'name':related.opts.verbose_name}) + \
(' <a href="../../../../%s/%s/%s/">%s</a>' % \
(related.opts.app_label, related.opts.module_name, sub_obj._get_pk_val(), escape(str(sub_obj)))), []])
(_('One or more %(fieldname)s in %(name)s:') % {'fieldname': force_unicode(related.field.verbose_name), 'name': force_unicode(related.opts.verbose_name)}) + \
(u' <a href="../../../../%s/%s/%s/">%s</a>' % \
(related.opts.app_label, related.opts.module_name, sub_obj._get_pk_val(), escape(sub_obj))), []])
# If there were related objects, and the user doesn't have
# permission to change them, add the missing perm to perms_needed.
if related.opts.admin and has_related_objs:
p = '%s.%s' % (related.opts.app_label, related.opts.get_change_permission())
p = u'%s.%s' % (related.opts.app_label, related.opts.get_change_permission())
if not user.has_perm(p):
perms_needed.add(related.opts.verbose_name)
@ -505,21 +507,21 @@ def delete_stage(request, app_label, model_name, object_id):
# Populate deleted_objects, a data structure of all related objects that
# will also be deleted.
deleted_objects = ['%s: <a href="../../%s/">%s</a>' % (capfirst(opts.verbose_name), object_id, escape(str(obj))), []]
deleted_objects = [u'%s: <a href="../../%s/">%s</a>' % (force_unicode(capfirst(opts.verbose_name)), force_unicode(object_id), escape(obj)), []]
perms_needed = set()
_get_deleted_objects(deleted_objects, perms_needed, request.user, obj, opts, 1)
if request.POST: # The user has already confirmed the deletion.
if perms_needed:
raise PermissionDenied
obj_display = str(obj)
obj_display = force_unicode(obj)
obj.delete()
LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, object_id, obj_display, DELETION)
request.user.message_set.create(message=_('The %(name)s "%(obj)s" was deleted successfully.') % {'name': opts.verbose_name, 'obj': obj_display})
request.user.message_set.create(message=_('The %(name)s "%(obj)s" was deleted successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': obj_display})
return HttpResponseRedirect("../../")
extra_context = {
"title": _("Are you sure?"),
"object_name": opts.verbose_name,
"object_name": force_unicode(opts.verbose_name),
"object": obj,
"deleted_objects": deleted_objects,
"perms_lacking": perms_needed,
@ -542,7 +544,7 @@ def history(request, app_label, model_name, object_id):
extra_context = {
'title': _('Change history: %s') % obj,
'action_list': action_list,
'module_name': capfirst(model._meta.verbose_name_plural),
'module_name': force_unicode(capfirst(model._meta.verbose_name_plural)),
'object': obj,
}
return render_to_response(["admin/%s/%s/object_history.html" % (app_label, model._meta.object_name.lower()),
@ -574,7 +576,7 @@ class ChangeList(object):
self.query = request.GET.get(SEARCH_VAR, '')
self.query_set = self.get_query_set()
self.get_results(request)
self.title = (self.is_popup and _('Select %s') % self.opts.verbose_name or _('Select %s to change') % self.opts.verbose_name)
self.title = (self.is_popup and _('Select %s') % force_unicode(self.opts.verbose_name) or _('Select %s to change') % force_unicode(self.opts.verbose_name))
self.filter_specs, self.has_filters = self.get_filters(request)
self.pk_attname = self.lookup_opts.pk.attname
@ -602,7 +604,7 @@ class ChangeList(object):
del p[k]
elif v is not None:
p[k] = v
return '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
return '?' + '&amp;'.join([u'%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
def get_results(self, request):
paginator = ObjectPaginator(self.query_set, self.lookup_opts.admin.list_per_page)
@ -671,7 +673,7 @@ class ChangeList(object):
try:
attr = getattr(lookup_opts.admin.manager.model, field_name)
order_field = attr.admin_order_field
except IndexError:
except AttributeError:
pass
else:
if not isinstance(f.rel, models.ManyToOneRel) or not f.null:
@ -688,6 +690,12 @@ class ChangeList(object):
for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR):
if i in lookup_params:
del lookup_params[i]
for key, value in lookup_params.items():
if not isinstance(key, str):
# 'key' will be used as a keyword argument later, so Python
# requires it to be a string.
del lookup_params[key]
lookup_params[smart_str(key)] = value
# Apply lookup parameters from the query string.
qs = qs.filter(**lookup_params)

View File

@ -12,6 +12,8 @@ def load_backend(path):
mod = __import__(module, {}, {}, [attr])
except ImportError, e:
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
except ValueError, e:
raise ImproperlyConfigured, 'Error importing authentication backends. Is AUTHENTICATION_BACKENDS a correctly defined list or tuple?'
try:
cls = getattr(mod, attr)
except AttributeError:

View File

@ -4,16 +4,16 @@ from django.contrib.sites.models import Site
from django.template import Context, loader
from django.core import validators
from django import oldforms
from django.utils.translation import gettext as _
from django.utils.translation import ugettext as _
class UserCreationForm(oldforms.Manipulator):
"A form that creates a user, with no privileges, from the given username and password."
def __init__(self):
self.fields = (
oldforms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
oldforms.TextField(field_name='username', length=30, max_length=30, is_required=True,
validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
oldforms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
)
@ -42,9 +42,9 @@ class AuthenticationForm(oldforms.Manipulator):
"""
self.request = request
self.fields = [
oldforms.TextField(field_name="username", length=15, maxlength=30, is_required=True,
oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
validator_list=[self.isValidUser, self.hasCookiesEnabled]),
oldforms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True),
oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
]
self.user_cache = None
@ -111,11 +111,11 @@ class PasswordChangeForm(oldforms.Manipulator):
def __init__(self, user):
self.user = user
self.fields = (
oldforms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True,
oldforms.PasswordField(field_name="old_password", length=30, max_length=30, is_required=True,
validator_list=[self.isValidOldPassword]),
oldforms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True,
oldforms.PasswordField(field_name="new_password1", length=30, max_length=30, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
oldforms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True),
oldforms.PasswordField(field_name="new_password2", length=30, max_length=30, is_required=True),
)
def isValidOldPassword(self, new_data, all_data):
@ -133,8 +133,8 @@ class AdminPasswordChangeForm(oldforms.Manipulator):
def __init__(self, user):
self.user = user
self.fields = (
oldforms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
)

View File

@ -7,13 +7,13 @@ from django.db.models import get_models, signals
from django.contrib.auth import models as auth_app
def _get_permission_codename(action, opts):
return '%s_%s' % (action, opts.object_name.lower())
return u'%s_%s' % (action, opts.object_name.lower())
def _get_all_permissions(opts):
"Returns (codename, name) for all permissions in the given opts."
perms = []
for action in ('add', 'change', 'delete'):
perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name)))
perms.append((_get_permission_codename(action, opts), u'Can %s %s' % (action, opts.verbose_name_raw)))
return perms + list(opts.permissions)
def create_permissions(app, created_models, verbosity):

View File

@ -1,9 +1,13 @@
from django.core import validators
from django.core.exceptions import ImproperlyConfigured
from django.db import backend, connection, models
from django.db import connection, models
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _
from django.utils.encoding import smart_str
from django.utils.translation import ugettext_lazy as _
import datetime
import urllib
UNUSABLE_PASSWORD = '!' # This will never be a valid hash
try:
set
@ -18,16 +22,16 @@ def check_password(raw_password, enc_password):
algo, salt, hsh = enc_password.split('$')
if algo == 'md5':
import md5
return hsh == md5.new(salt+raw_password).hexdigest()
return hsh == md5.new(smart_str(salt + raw_password)).hexdigest()
elif algo == 'sha1':
import sha
return hsh == sha.new(salt+raw_password).hexdigest()
return hsh == sha.new(smart_str(salt + raw_password)).hexdigest()
elif algo == 'crypt':
try:
import crypt
except ImportError:
raise ValueError, "Crypt password algorithm not supported in this environment."
return hsh == crypt.crypt(raw_password, salt)
return hsh == crypt.crypt(smart_str(raw_password), smart_str(salt))
raise ValueError, "Got unknown password algorithm type in password."
class SiteProfileNotAvailable(Exception):
@ -46,9 +50,9 @@ class Permission(models.Model):
Three basic permissions -- add, change and delete -- are automatically created for each Django model.
"""
name = models.CharField(_('name'), maxlength=50)
name = models.CharField(_('name'), max_length=50)
content_type = models.ForeignKey(ContentType)
codename = models.CharField(_('codename'), maxlength=100)
codename = models.CharField(_('codename'), max_length=100)
class Meta:
verbose_name = _('permission')
@ -56,8 +60,8 @@ class Permission(models.Model):
unique_together = (('content_type', 'codename'),)
ordering = ('content_type', 'codename')
def __str__(self):
return "%s | %s | %s" % (self.content_type.app_label, self.content_type, self.name)
def __unicode__(self):
return u"%s | %s | %s" % (self.content_type.app_label, self.content_type, self.name)
class Group(models.Model):
"""Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups.
@ -66,7 +70,7 @@ class Group(models.Model):
Beyond permissions, groups are a convenient way to categorize users to apply some label, or extended functionality, to them. For example, you could create a group 'Special users', and you could write code that would do special things to those users -- such as giving them access to a members-only portion of your site, or sending them members-only e-mail messages.
"""
name = models.CharField(_('name'), maxlength=80, unique=True)
name = models.CharField(_('name'), max_length=80, unique=True)
permissions = models.ManyToManyField(Permission, verbose_name=_('permissions'), blank=True, filter_interface=models.HORIZONTAL)
class Meta:
@ -77,15 +81,18 @@ class Group(models.Model):
class Admin:
search_fields = ('name',)
def __str__(self):
def __unicode__(self):
return self.name
class UserManager(models.Manager):
def create_user(self, username, email, password):
def create_user(self, username, email, password=None):
"Creates and saves a User with the given username, e-mail and password."
now = datetime.datetime.now()
user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
if password:
user.set_password(password)
else:
user.set_unusable_password()
user.save()
return user
@ -101,11 +108,11 @@ class User(models.Model):
Username and password are required. Other fields are optional.
"""
username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
first_name = models.CharField(_('first name'), maxlength=30, blank=True)
last_name = models.CharField(_('last name'), maxlength=30, blank=True)
username = models.CharField(_('username'), max_length=30, unique=True, validator_list=[validators.isAlphaNumeric], help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('e-mail address'), blank=True)
password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
password = models.CharField(_('password'), max_length=128, help_text=_("Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts."))
is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
@ -133,11 +140,11 @@ class User(models.Model):
list_filter = ('is_staff', 'is_superuser')
search_fields = ('username', 'first_name', 'last_name', 'email')
def __str__(self):
def __unicode__(self):
return self.username
def get_absolute_url(self):
return "/users/%s/" % self.username
return "/users/%s/" % urllib.quote(smart_str(self.username))
def is_anonymous(self):
"Always returns False. This is a way of comparing User objects to anonymous users."
@ -150,14 +157,14 @@ class User(models.Model):
def get_full_name(self):
"Returns the first_name plus the last_name, with a space in between."
full_name = '%s %s' % (self.first_name, self.last_name)
full_name = u'%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def set_password(self, raw_password):
import sha, random
algo = 'sha1'
salt = sha.new(str(random.random())).hexdigest()[:5]
hsh = sha.new(salt+raw_password).hexdigest()
hsh = sha.new(salt + smart_str(raw_password)).hexdigest()
self.password = '%s$%s$%s' % (algo, salt, hsh)
def check_password(self, raw_password):
@ -169,7 +176,7 @@ class User(models.Model):
# algorithm or salt.
if '$' not in self.password:
import md5
is_correct = (self.password == md5.new(raw_password).hexdigest())
is_correct = (self.password == md5.new(smart_str(raw_password)).hexdigest())
if is_correct:
# Convert the password to the new, more secure format.
self.set_password(raw_password)
@ -177,6 +184,13 @@ class User(models.Model):
return is_correct
return check_password(raw_password, self.password)
def set_unusable_password(self):
# Sets a value that will never be a valid hash
self.password = UNUSABLE_PASSWORD
def has_usable_password(self):
return self.password != UNUSABLE_PASSWORD
def get_group_permissions(self):
"Returns a list of permission strings that this user has through his/her groups."
if not hasattr(self, '_group_perm_cache'):
@ -189,6 +203,7 @@ class User(models.Model):
# AND gp."group_id" = ug."group_id"
# AND ct."id" = p."content_type_id"
# AND ug."user_id" = %s, [self.id])
qn = connection.ops.quote_name
sql = """
SELECT ct.%s, p.%s
FROM %s p, %s gp, %s ug, %s ct
@ -196,20 +211,20 @@ class User(models.Model):
AND gp.%s = ug.%s
AND ct.%s = p.%s
AND ug.%s = %%s""" % (
backend.quote_name('app_label'), backend.quote_name('codename'),
backend.quote_name('auth_permission'), backend.quote_name('auth_group_permissions'),
backend.quote_name('auth_user_groups'), backend.quote_name('django_content_type'),
backend.quote_name('id'), backend.quote_name('permission_id'),
backend.quote_name('group_id'), backend.quote_name('group_id'),
backend.quote_name('id'), backend.quote_name('content_type_id'),
backend.quote_name('user_id'),)
qn('app_label'), qn('codename'),
qn('auth_permission'), qn('auth_group_permissions'),
qn('auth_user_groups'), qn('django_content_type'),
qn('id'), qn('permission_id'),
qn('group_id'), qn('group_id'),
qn('id'), qn('content_type_id'),
qn('user_id'),)
cursor.execute(sql, [self.id])
self._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
return self._group_perm_cache
def get_all_permissions(self):
if not hasattr(self, '_perm_cache'):
self._perm_cache = set(["%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.select_related()])
self._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.select_related()])
self._perm_cache.update(self.get_group_permissions())
return self._perm_cache
@ -266,12 +281,13 @@ class User(models.Model):
return self._profile_cache
class Message(models.Model):
"""The message system is a lightweight way to queue messages for given users. A message is associated with a User instance (so it is only applicable for registered users). There's no concept of expiration or timestamps. Messages are created by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message.
"""
The message system is a lightweight way to queue messages for given users. A message is associated with a User instance (so it is only applicable for registered users). There's no concept of expiration or timestamps. Messages are created by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message.
"""
user = models.ForeignKey(User)
message = models.TextField(_('message'))
def __str__(self):
def __unicode__(self):
return self.message
class AnonymousUser(object):
@ -281,8 +297,11 @@ class AnonymousUser(object):
def __init__(self):
pass
def __unicode__(self):
return 'AnonymousUser'
def __str__(self):
return _('AnonymousUser')
return unicode(self).encode('utf-8')
def __eq__(self, other):
return isinstance(other, self.__class__)

View File

@ -0,0 +1,19 @@
"""
>>> from models import User
>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
>>> u.has_usable_password()
True
>>> u.check_password('bad')
False
>>> u.check_password('testpw')
True
>>> u.set_unusable_password()
>>> u.save()
>>> u.check_password('testpw')
False
>>> u.has_usable_password()
False
>>> u2 = User.objects.create_user('testuser2', 'test2@example.com')
>>> u2.has_usable_password()
False
"""

View File

@ -3,10 +3,11 @@ from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm
from django import oldforms
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.sites.models import Site
from django.contrib.sites.models import Site, RequestSite
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.utils.translation import ugettext as _
def login(request, template_name='registration/login.html'):
"Displays the login form and handles the login action."
@ -26,10 +27,16 @@ def login(request, template_name='registration/login.html'):
else:
errors = {}
request.session.set_test_cookie()
if Site._meta.installed:
current_site = Site.objects.get_current()
else:
current_site = RequestSite(request)
return render_to_response(template_name, {
'form': oldforms.FormWrapper(manipulator, request.POST, errors),
REDIRECT_FIELD_NAME: redirect_to,
'site_name': Site.objects.get_current().name,
'site_name': current_site.name,
}, context_instance=RequestContext(request))
def logout(request, next_page=None, template_name='registration/logged_out.html'):

View File

@ -11,7 +11,7 @@ class LatestFreeCommentsFeed(Feed):
def title(self):
if not hasattr(self, '_site'):
self._site = Site.objects.get_current()
return "%s comments" % self._site.name
return u"%s comments" % self._site.name
def link(self):
if not hasattr(self, '_site'):
@ -21,7 +21,7 @@ class LatestFreeCommentsFeed(Feed):
def description(self):
if not hasattr(self, '_site'):
self._site = Site.objects.get_current()
return "Latest comments on %s" % self._site.name
return u"Latest comments on %s" % self._site.name
def get_query_set(self):
return self.comments_class.objects.filter(site__pk=settings.SITE_ID, is_public=True)

View File

@ -2,7 +2,7 @@ from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
import datetime
@ -65,8 +65,8 @@ class Comment(models.Model):
user = models.ForeignKey(User, raw_id_admin=True)
content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID'))
headline = models.CharField(_('headline'), maxlength=255, blank=True)
comment = models.TextField(_('comment'), maxlength=3000)
headline = models.CharField(_('headline'), max_length=255, blank=True)
comment = models.TextField(_('comment'), max_length=3000)
rating1 = models.PositiveSmallIntegerField(_('rating #1'), blank=True, null=True)
rating2 = models.PositiveSmallIntegerField(_('rating #2'), blank=True, null=True)
rating3 = models.PositiveSmallIntegerField(_('rating #3'), blank=True, null=True)
@ -106,7 +106,10 @@ class Comment(models.Model):
return "%s: %s..." % (self.user.username, self.comment[:100])
def get_absolute_url(self):
try:
return self.get_content_object().get_absolute_url() + "#c" + str(self.id)
except AttributeError:
return ""
def get_crossdomain_url(self):
return "/r/%d/%d/" % (self.content_type_id, self.object_id)
@ -164,8 +167,8 @@ class FreeComment(models.Model):
# A FreeComment is a comment by a non-registered user.
content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID'))
comment = models.TextField(_('comment'), maxlength=3000)
person_name = models.CharField(_("person's name"), maxlength=50)
comment = models.TextField(_('comment'), max_length=3000)
person_name = models.CharField(_("person's name"), max_length=50)
submit_date = models.DateTimeField(_('date/time submitted'), auto_now_add=True)
is_public = models.BooleanField(_('is public'))
ip_address = models.IPAddressField(_('ip address'))
@ -191,7 +194,10 @@ class FreeComment(models.Model):
return "%s: %s..." % (self.person_name, self.comment[:100])
def get_absolute_url(self):
try:
return self.get_content_object().get_absolute_url() + "#c" + str(self.id)
except AttributeError:
return ""
def get_content_object(self):
"""

View File

@ -5,6 +5,7 @@ from django import template
from django.template import loader
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_str
import re
register = template.Library()
@ -111,9 +112,9 @@ class CommentListNode(template.Node):
'site__id__exact': settings.SITE_ID,
}
kwargs.update(self.extra_kwargs)
if not self.free and settings.COMMENTS_BANNED_USERS_GROUP:
kwargs['select'] = {'is_hidden': 'user_id IN (SELECT user_id FROM auth_user_groups WHERE group_id = %s)' % settings.COMMENTS_BANNED_USERS_GROUP}
comment_list = get_list_function(**kwargs).order_by(self.ordering + 'submit_date').select_related()
if not self.free and settings.COMMENTS_BANNED_USERS_GROUP:
comment_list = comment_list.extra(select={'is_hidden': 'user_id IN (SELECT user_id FROM auth_user_groups WHERE group_id = %s)' % settings.COMMENTS_BANNED_USERS_GROUP})
if not self.free:
if 'user' in context and context['user'].is_authenticated():
@ -174,6 +175,7 @@ class DoCommentForm:
if tokens[4] != 'with':
raise template.TemplateSyntaxError, "Fourth argument in %r tag must be 'with'" % tokens[0]
for option, args in zip(tokens[5::2], tokens[6::2]):
option = smart_str(option)
if option in ('photos_optional', 'photos_required') and not self.free:
# VALIDATION ##############################################
option_list = args.split(',')

View File

@ -11,7 +11,8 @@ from django.contrib.auth.forms import AuthenticationForm
from django.http import HttpResponseRedirect
from django.utils.text import normalize_newlines
from django.conf import settings
from django.utils.translation import ngettext
from django.utils.translation import ungettext, ugettext as _
from django.utils.encoding import smart_unicode
import base64, datetime
COMMENTS_PER_PAGE = 20
@ -28,7 +29,7 @@ class PublicCommentManipulator(AuthenticationForm):
else:
return []
self.fields.extend([
oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
oldforms.LargeTextField(field_name="comment", max_length=3000, is_required=True,
validator_list=[self.hasNoProfanities]),
oldforms.RadioSelectField(field_name="rating1", choices=choices,
is_required=ratings_required and num_rating_choices > 0,
@ -108,11 +109,11 @@ class PublicCommentManipulator(AuthenticationForm):
# If the commentor has posted fewer than COMMENTS_FIRST_FEW comments,
# send the comment to the managers.
if self.user_cache.comment_set.count() <= settings.COMMENTS_FIRST_FEW:
message = ngettext('This comment was posted by a user who has posted fewer than %(count)s comment:\n\n%(text)s',
message = ungettext('This comment was posted by a user who has posted fewer than %(count)s comment:\n\n%(text)s',
'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s', settings.COMMENTS_FIRST_FEW) % \
{'count': settings.COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
mail_managers("Comment posted by rookie user", message)
if settings.COMMENTS_SKETCHY_USERS_GROUP and settings.COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.get_group_list()]:
if settings.COMMENTS_SKETCHY_USERS_GROUP and settings.COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.groups.all()]:
message = _('This comment was posted by a sketchy user:\n\n%(text)s') % {'text': c.get_as_text()}
mail_managers("Comment posted by sketchy user (%s)" % self.user_cache.username, c.get_as_text())
return c
@ -121,9 +122,9 @@ class PublicFreeCommentManipulator(oldforms.Manipulator):
"Manipulator that handles public free (unregistered) comments"
def __init__(self):
self.fields = (
oldforms.TextField(field_name="person_name", maxlength=50, is_required=True,
oldforms.TextField(field_name="person_name", max_length=50, is_required=True,
validator_list=[self.hasNoProfanities]),
oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
oldforms.LargeTextField(field_name="comment", max_length=3000, is_required=True,
validator_list=[self.hasNoProfanities]),
)
@ -248,7 +249,7 @@ def post_comment(request):
# If the IP is banned, mail the admins, do NOT save the comment, and
# serve up the "Thanks for posting" page as if the comment WAS posted.
if request.META['REMOTE_ADDR'] in settings.BANNED_IPS:
mail_admins("Banned IP attempted to post comment", str(request.POST) + "\n\n" + str(request.META))
mail_admins("Banned IP attempted to post comment", smart_unicode(request.POST) + "\n\n" + str(request.META))
else:
manipulator.do_html2python(new_data)
comment = manipulator.save(new_data)
@ -312,7 +313,7 @@ def post_free_comment(request):
# serve up the "Thanks for posting" page as if the comment WAS posted.
if request.META['REMOTE_ADDR'] in settings.BANNED_IPS:
from django.core.mail import mail_admins
mail_admins("Practical joker", str(request.POST) + "\n\n" + str(request.META))
mail_admins("Practical joker", smart_unicode(request.POST) + "\n\n" + str(request.META))
else:
manipulator.do_html2python(new_data)
comment = manipulator.save(new_data)

View File

@ -2,6 +2,7 @@ from django.http import Http404
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.comments.models import Comment, KarmaScore
from django.utils.translation import ugettext as _
def vote(request, comment_id, vote):
"""

View File

@ -4,7 +4,7 @@ Classes allowing "generic" relations through ContentType and object-id fields.
from django import oldforms
from django.core.exceptions import ObjectDoesNotExist
from django.db import backend
from django.db import connection
from django.db.models import signals
from django.db.models.fields.related import RelatedField, Field, ManyToManyRel
from django.db.models.loading import get_model
@ -49,7 +49,7 @@ class GenericForeignKey(object):
def __get__(self, instance, instance_type=None):
if instance is None:
raise AttributeError, "%s must be accessed via instance" % self.name
raise AttributeError, u"%s must be accessed via instance" % self.name
try:
return getattr(instance, self.cache_attr)
@ -66,7 +66,7 @@ class GenericForeignKey(object):
def __set__(self, instance, value):
if instance is None:
raise AttributeError, "%s must be accessed via instance" % self.related.opts.object_name
raise AttributeError, u"%s must be accessed via instance" % self.related.opts.object_name
ct = None
fk = None
@ -163,13 +163,15 @@ class ReverseGenericRelatedObjectsDescriptor(object):
superclass = rel_model._default_manager.__class__
RelatedManager = create_generic_related_manager(superclass)
qn = connection.ops.quote_name
manager = RelatedManager(
model = rel_model,
instance = instance,
symmetrical = (self.field.rel.symmetrical and instance.__class__ == rel_model),
join_table = backend.quote_name(self.field.m2m_db_table()),
source_col_name = backend.quote_name(self.field.m2m_column_name()),
target_col_name = backend.quote_name(self.field.m2m_reverse_name()),
join_table = qn(self.field.m2m_db_table()),
source_col_name = qn(self.field.m2m_column_name()),
target_col_name = qn(self.field.m2m_reverse_name()),
content_type = ContentType.objects.get_for_model(self.field.model),
content_type_field_name = self.field.content_type_field_name,
object_id_field_name = self.field.object_id_field_name

View File

@ -4,6 +4,7 @@ Creates content types for all installed models.
from django.dispatch import dispatcher
from django.db.models import get_apps, get_models, signals
from django.utils.encoding import smart_unicode
def create_contenttypes(app, created_models, verbosity=2):
from django.contrib.contenttypes.models import ContentType
@ -17,7 +18,7 @@ def create_contenttypes(app, created_models, verbosity=2):
ContentType.objects.get(app_label=opts.app_label,
model=opts.object_name.lower())
except ContentType.DoesNotExist:
ct = ContentType(name=str(opts.verbose_name),
ct = ContentType(name=smart_unicode(opts.verbose_name_raw),
app_label=opts.app_label, model=opts.object_name.lower())
ct.save()
if verbosity >= 2:

View File

@ -1,5 +1,6 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
CONTENT_TYPE_CACHE = {}
class ContentTypeManager(models.Manager):
@ -13,10 +14,10 @@ class ContentTypeManager(models.Manager):
try:
ct = CONTENT_TYPE_CACHE[key]
except KeyError:
# The str() is needed around opts.verbose_name because it's a
# django.utils.functional.__proxy__ object.
# The smart_unicode() is needed around opts.verbose_name_raw because it might
# be a django.utils.functional.__proxy__ object.
ct, created = self.model._default_manager.get_or_create(app_label=key[0],
model=key[1], defaults={'name': str(opts.verbose_name)})
model=key[1], defaults={'name': smart_unicode(opts.verbose_name_raw)})
CONTENT_TYPE_CACHE[key] = ct
return ct
@ -31,9 +32,9 @@ class ContentTypeManager(models.Manager):
CONTENT_TYPE_CACHE = {}
class ContentType(models.Model):
name = models.CharField(maxlength=100)
app_label = models.CharField(maxlength=100)
model = models.CharField(_('python model class name'), maxlength=100)
name = models.CharField(max_length=100)
app_label = models.CharField(max_length=100)
model = models.CharField(_('python model class name'), max_length=100)
objects = ContentTypeManager()
class Meta:
verbose_name = _('content type')
@ -42,7 +43,7 @@ class ContentType(models.Model):
ordering = ('name',)
unique_together = (('app_label', 'model'),)
def __str__(self):
def __unicode__(self):
return self.name
def model_class(self):

View File

@ -7,6 +7,8 @@ from django.db import models
from django.utils import dateformat
from django.utils.text import capfirst
from django.utils.translation import get_date_formats
from django.utils.encoding import smart_unicode, smart_str, iri_to_uri
from django.db.models.query import QuerySet
EMPTY_VALUE = '(None)'
@ -19,7 +21,7 @@ class EasyModel(object):
self.verbose_name_plural = model._meta.verbose_name_plural
def __repr__(self):
return '<EasyModel for %s>' % self.model._meta.object_name
return '<EasyModel for %s>' % smart_str(self.model._meta.object_name)
def model_databrowse(self):
"Returns the ModelDatabrowse class for this model."
@ -29,8 +31,12 @@ class EasyModel(object):
return '%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name)
def objects(self, **kwargs):
for obj in self.model._default_manager.filter(**kwargs):
yield EasyInstance(self, obj)
return self.get_query_set().filter(**kwargs)
def get_query_set(self):
easy_qs = self.model._default_manager.get_query_set()._clone(klass=EasyQuerySet)
easy_qs._easymodel = self
return easy_qs
def object_by_pk(self, pk):
return EasyInstance(self, self.model._default_manager.get(pk=pk))
@ -54,7 +60,7 @@ class EasyField(object):
self.model, self.field = easy_model, field
def __repr__(self):
return '<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name)
return smart_str(u'<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def choices(self):
for value, label in self.field.choices:
@ -72,29 +78,32 @@ class EasyChoice(object):
self.value, self.label = value, label
def __repr__(self):
return '<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name)
return smart_str(u'<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def url(self):
return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, self.value)
return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, iri_to_uri(self.value))
class EasyInstance(object):
def __init__(self, easy_model, instance):
self.model, self.instance = easy_model, instance
def __repr__(self):
return '<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val())
return smart_str(u'<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()))
def __unicode__(self):
val = smart_unicode(self.instance)
if len(val) > 30:
return val[:30] + u'...'
return val
def __str__(self):
val = str(self.instance)
if len(val) > 30:
return val[:30] + '...'
return val
return self.__unicode__().encode('utf-8')
def pk(self):
return self.instance._get_pk_val()
def url(self):
return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.pk())
return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk()))
def fields(self):
"""
@ -126,7 +135,7 @@ class EasyInstanceField(object):
self.raw_value = getattr(instance.instance, field.name)
def __repr__(self):
return '<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name)
return smart_str(u'<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def values(self):
"""
@ -175,18 +184,32 @@ class EasyInstanceField(object):
if self.field.rel.to in self.model.model_list:
lst = []
for value in self.values():
url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, value._get_pk_val())
lst.append((str(value), url))
url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, iri_to_uri(value._get_pk_val()))
lst.append((smart_unicode(value), url))
else:
lst = [(value, None) for value in self.values()]
elif self.field.choices:
lst = []
for value in self.values():
url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, self.raw_value)
url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, iri_to_uri(self.raw_value))
lst.append((value, url))
elif isinstance(self.field, models.URLField):
val = self.values()[0]
lst = [(val, val)]
lst = [(val, iri_to_uri(val))]
else:
lst = [(self.values()[0], None)]
return lst
class EasyQuerySet(QuerySet):
"""
When creating (or cloning to) an `EasyQuerySet`, make sure to set the
`_easymodel` variable to the related `EasyModel`.
"""
def iterator(self, *args, **kwargs):
for obj in super(EasyQuerySet, self).iterator(*args, **kwargs):
yield EasyInstance(self._easymodel, obj)
def _clone(self, *args, **kwargs):
c = super(EasyQuerySet, self)._clone(*args, **kwargs)
c._easymodel = self._easymodel
return c

View File

@ -6,6 +6,7 @@ from django.shortcuts import render_to_response
from django.utils.text import capfirst
from django.utils.translation import get_date_formats
from django.views.generic import date_based
from django.utils.encoding import force_unicode
import datetime
import time
@ -27,13 +28,13 @@ class CalendarPlugin(DatabrowsePlugin):
def model_index_html(self, request, model, site):
fields = self.field_dict(model)
if not fields:
return ''
return '<p class="filter"><strong>View calendar by:</strong> %s</p>' % \
', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()])
return u''
return u'<p class="filter"><strong>View calendar by:</strong> %s</p>' % \
u', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()])
def urls(self, plugin_name, easy_instance_field):
if isinstance(easy_instance_field.field, models.DateField):
return ['%s%s/%s/%s/%s/%s/' % (easy_instance_field.model.url(),
return [u'%s%s/%s/%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
easy_instance_field.raw_value.year,
easy_instance_field.raw_value.strftime('%b').lower(),
@ -63,22 +64,22 @@ class CalendarPlugin(DatabrowsePlugin):
def calendar_view(self, request, field, year=None, month=None, day=None):
easy_model = EasyModel(self.site, self.model)
queryset = easy_model.get_query_set()
extra_context = {'root_url': self.site.root_url, 'model': easy_model, 'field': field}
if day is not None:
# TODO: The objects in this template should be EasyInstances
return date_based.archive_day(request, year, month, day, self.model.objects.all(), field.name,
return date_based.archive_day(request, year, month, day, queryset, field.name,
template_name='databrowse/calendar_day.html', allow_empty=False, allow_future=True,
extra_context=extra_context)
elif month is not None:
return date_based.archive_month(request, year, month, self.model.objects.all(), field.name,
return date_based.archive_month(request, year, month, queryset, field.name,
template_name='databrowse/calendar_month.html', allow_empty=False, allow_future=True,
extra_context=extra_context)
elif year is not None:
return date_based.archive_year(request, year, self.model.objects.all(), field.name,
return date_based.archive_year(request, year, queryset, field.name,
template_name='databrowse/calendar_year.html', allow_empty=False, allow_future=True,
extra_context=extra_context)
else:
return date_based.archive_index(request, self.model.objects.all(), field.name,
return date_based.archive_index(request, queryset, field.name,
template_name='databrowse/calendar_main.html', allow_empty=True, allow_future=True,
extra_context=extra_context)
assert False, ('%s, %s, %s, %s' % (field, year, month, day))

View File

@ -4,9 +4,11 @@ from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
from django.utils.text import capfirst
from django.utils.encoding import smart_str, force_unicode
from django.views.generic import date_based
import datetime
import time
import urllib
class FieldChoicePlugin(DatabrowsePlugin):
def __init__(self, field_filter=None):
@ -29,15 +31,16 @@ class FieldChoicePlugin(DatabrowsePlugin):
def model_index_html(self, request, model, site):
fields = self.field_dict(model)
if not fields:
return ''
return '<p class="filter"><strong>View by:</strong> %s</p>' % \
', '.join(['<a href="fields/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()])
return u''
return u'<p class="filter"><strong>View by:</strong> %s</p>' % \
u', '.join(['<a href="fields/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()])
def urls(self, plugin_name, easy_instance_field):
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
return ['%s%s/%s/%s/' % (easy_instance_field.model.url(),
field_value = smart_str(easy_instance_field.raw_value)
return [u'%s%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
easy_instance_field.raw_value)]
urllib.quote(field_value, safe=''))]
def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site

View File

@ -60,7 +60,7 @@ class ModelDatabrowse(object):
def main_view(self, request):
easy_model = EasyModel(self.site, self.model)
html_snippets = '\n'.join([p.model_index_html(request, self.model, self.site) for p in self.plugins.values()])
html_snippets = u'\n'.join([p.model_index_html(request, self.model, self.site) for p in self.plugins.values()])
return render_to_response('databrowse/model_detail.html', {
'model': easy_model,
'root_url': self.site.root_url,

View File

@ -2,6 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{% block title %}{% endblock %}</title>
{% block style %}
<style type="text/css">
* { margin:0; padding:0; }
body { background:#eee; color:#333; font:76%/1.6 "Lucida Grande","Bitstream Vera Sans",Verdana,sans-serif; }
@ -48,9 +49,11 @@ p { margin:0.5em 0 1em 0; }
/* CONTENT */
#content { background:#fff; border-bottom:1px solid #ddd; padding:0 20px; }
</style>
{% endblock %}
{% block extrahead %}{% endblock %}
</head>
<body id="{% block bodyid %}page{% endblock %}">
<div id="header"><a href="{{ root_url }}">Databrowse</a></div>
<div id="header"><a href="{{ root_url }}">{% block databrowse_title %}Databrowse{% endblock %}</a></div>
<div id="content">
{% block content %}{% endblock %}
</div>

View File

@ -0,0 +1 @@
{% extends "databrowse/base.html" %}

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} {{ day|date:"F j, Y" }}{% endblock %}
@ -6,11 +6,11 @@
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../../../">Calendars</a> / <a href="../../../">By {{ field.verbose_name }}</a> / <a href="../../">{{ day.year }}</a> / <a href="../">{{ day|date:"F" }}</a> / {{ day.day }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} on {{ day|date:"F j, Y" }}</h1>
<h1>{{ object_list.count }} {% if object_list.count|pluralize %}{{ model.verbose_name_plural|escape }}{% else %}{{ model.verbose_name|escape }}{% endif %} with {{ field.verbose_name }} on {{ day|date:"F j, Y" }}</h1>
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}Calendars{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ field.verbose_name|capfirst }} calendar{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ month|date:"F Y" }}{% endblock %}
@ -6,11 +6,11 @@
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../../">Calendars</a> / <a href="../../">By {{ field.verbose_name }}</a> / <a href="../">{{ month.year }}</a> / {{ month|date:"F" }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ month|date:"F Y" }}</h1>
<h1>{{ object_list.count }} {% if object_list.count|pluralize %}{{ model.verbose_name_plural|escape }}{% else %}{{ model.verbose_name|escape }}{% endif %} with {{ field.verbose_name }} on {{ day|date:"F Y" }}</h1>
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ year }}{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}: {{ value|escape }}{% endblock %}
@ -10,7 +10,7 @@
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}{% endblock %}
@ -10,7 +10,7 @@
<ul class="objectlist">
{% for choice in field.choices %}
<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst|escape }} with {{ field.field.verbose_name|escape }} {{ value|escape }}{% endblock %}
@ -6,7 +6,7 @@
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../">Fields</a> / <a href="../">By {{ field.field.verbose_name|escape }}</a> / {{ value|escape }}</div>
<h1>{{ model.verbose_name_plural|capfirst|escape }} with {{ field.field.verbose_name|escape }} {{ value|escape }}</h1>
<h1>{{ object_list.count }} {% if object_list.count|pluralize %}{{ model.verbose_name_plural|escape }}{% else %}{{ model.verbose_name|escape }}{% endif %} with {{ field.field.verbose_name|escape }} {{ value|escape }}</h1>
<ul class="objectlist">
{% for object in object_list %}

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}Browsable fields in {{ model.verbose_name_plural|escape }}{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst|escape }} by {{ field.field.verbose_name|escape }}{% endblock %}
@ -10,7 +10,7 @@
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object }}/">{{ object|escape }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object|iriencode }}/">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}Databrowse{% endblock %}
@ -11,7 +11,7 @@
<h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2>
<p>
{% for object in model.sample_objects %}
<a href="{{ object.url }}">{{ object }}</a>,
<a href="{{ object.url }}">{{ object|escape }}</a>,
{% endfor %}
<a class="more" href="{{ model.url }}">More &rarr;</a>
</p>

View File

@ -1,4 +1,4 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }}{% endblock %}
@ -6,13 +6,13 @@
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / {{ model.verbose_name_plural|capfirst }}</div>
<h1>{{ model.verbose_name_plural|capfirst }}</h1>
<h1>{{ model.objects.count }} {% if model.objects.count|pluralize %}{{ model.verbose_name_plural }}{% else %}{{ model.verbose_name }}{% endif %}</h1>
{{ plugin_html }}
<ul class="objectlist">
{% for object in model.objects %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>

View File

@ -1,12 +1,12 @@
{% extends "databrowse/base.html" %}
{% extends "databrowse/base_site.html" %}
{% block title %}{{ object.model.verbose_name|capfirst }}: {{ object }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object }}</div>
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object|escape }}</div>
<h1>{{ object.model.verbose_name|capfirst }}: {{ object }}</h1>
<h1>{{ object.model.verbose_name|capfirst }}: {{ object|escape }}</h1>
<table class="objectinfo">
{% for field in object.fields %}
@ -14,8 +14,8 @@
<th>{{ field.field.verbose_name|capfirst }}</th>
<td>
{% if field.urls %}
{% for urlvalue in field.urls %}
{% if urlvalue.1 %}<a href="{{ urlvalue.1 }}">{% endif %}{{ urlvalue.0 }}{% if urlvalue.1 %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
{% for value, url in field.urls %}
{% if url %}<a href="{{ url }}">{% endif %}{{ value|escape }}{% if url %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
{% endfor %}
{% else %}None{% endif %}
</td>
@ -29,7 +29,7 @@
{% if related_object.object_list %}
<ul class="objectlist">
{% for object in related_object.object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>
{% else %}

View File

@ -1,15 +1,15 @@
from django.core import validators
from django.db import models
from django.contrib.sites.models import Site
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
class FlatPage(models.Model):
url = models.CharField(_('URL'), maxlength=100, validator_list=[validators.isAlphaNumericURL], db_index=True,
url = models.CharField(_('URL'), max_length=100, validator_list=[validators.isAlphaNumericURL], db_index=True,
help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes."))
title = models.CharField(_('title'), maxlength=200)
title = models.CharField(_('title'), max_length=200)
content = models.TextField(_('content'))
enable_comments = models.BooleanField(_('enable comments'))
template_name = models.CharField(_('template name'), maxlength=70, blank=True,
template_name = models.CharField(_('template name'), max_length=70, blank=True,
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)
@ -26,8 +26,8 @@ class FlatPage(models.Model):
list_filter = ('sites',)
search_fields = ('url', 'title')
def __str__(self):
return "%s -- %s" % (self.url, self.title)
def __unicode__(self):
return u"%s -- %s" % (self.url, self.title)
def get_absolute_url(self):
return self.url

View File

@ -12,9 +12,10 @@
additional spatial databases.
"""
from django.conf import settings
from django.db import backend
from django.db import connection
from django.db.models.query import LOOKUP_SEPARATOR, field_choices, find_field, FieldFound, QUERY_TERMS, get_where_clause
from django.utils.datastructures import SortedDict
qn = connection.ops.quote_name
if settings.DATABASE_ENGINE == 'postgresql_psycopg2':
# PostGIS is the spatial database, getting the rquired modules, renaming as necessary.
@ -89,7 +90,6 @@ def parse_lookup(kwarg_items, opts):
return joins, where, params
def lookup_inner(path, lookup_type, value, opts, table, column):
qn = backend.quote_name
joins, where, params = SortedDict(), [], []
current_opts = opts
current_table = table
@ -216,6 +216,7 @@ def lookup_inner(path, lookup_type, value, opts, table, column):
else:
# No elements left in path. Current element is the element on which
# the search is being performed.
db_type = None
if join_required:
# Last query term is a RelatedObject
@ -282,7 +283,7 @@ def lookup_inner(path, lookup_type, value, opts, table, column):
where.append(gwc)
params.extend(geo_params)
else:
where.append(get_where_clause(lookup_type, current_table + '.', column, value))
where.append(get_where_clause(lookup_type, current_table + '.', column, value, db_type))
params.extend(field.get_db_prep_lookup(lookup_type, value))
return joins, where, params

View File

@ -1,6 +1,6 @@
from django.conf import settings
from django.core.management import syncdb
from django.db import connection, backend
from django.core.management import call_command
from django.db import connection
from django.test.utils import _set_autocommit, TEST_DATABASE_PREFIX
from commands import getstatusoutput
import os, re, sys
@ -23,13 +23,12 @@ def create_lang(db_name, verbosity=1):
if status != 0:
raise Exception, "Error executing 'plpgsql' command: %s\n" % output
def _create_with_cursor(db_name, verbosity=1, autoclobber=False):
"Creates database with psycopg2 cursor."
# Constructing the necessary SQL to create the database (the DATABASE_USER
# must possess the privileges to create a database)
create_sql = 'CREATE DATABASE %s OWNER %s' % (backend.quote_name(db_name),
create_sql = 'CREATE DATABASE %s OWNER %s' % (connection.ops.quote_name(db_name),
settings.DATABASE_USER)
cursor = connection.cursor()
_set_autocommit(connection)
@ -113,7 +112,7 @@ def create_spatial_db(test=False, verbosity=1, autoclobber=False, interactive=Fa
settings.DATABASE_NAME = db_name
# Syncing the database
syncdb(verbosity, interactive=interactive)
call_command('syncdb', verbosity=verbosity, interactive=interactive)
# Get a cursor (even though we don't need one yet). This has
# the side effect of initializing the test database.
@ -123,7 +122,7 @@ def drop_db(db_name=False, test=False):
"Using the cursor, drops the given database. All exceptions will be propagated up."
if not db_name: db_name = get_spatial_db(test=test)
cursor = connection.cursor()
cursor.execute("DROP DATABASE %s" % backend.quote_name(db_name))
cursor.execute("DROP DATABASE %s" % connection.ops.quote_name(db_name))
def get_cmd_options(db_name):
"Obtains the command-line PostgreSQL connection options for shell commands."

View File

@ -2,9 +2,10 @@
This module contains the spatial lookup types, and the get_geo_where_clause()
routine for PostGIS.
"""
from django.db import backend
from django.db import connection
from django.contrib.gis.db.backend.postgis.management import postgis_version_tuple
from types import StringType, UnicodeType
quote_name = connection.ops.quote_name
# Getting the PostGIS version information
POSTGIS_VERSION, MAJOR_VERSION, MINOR_VERSION1, MINOR_VERSION2 = postgis_version_tuple()
@ -120,8 +121,8 @@ def get_geom_func(lookup_type):
def get_geo_where_clause(lookup_type, table_prefix, field_name, value):
"Returns the SQL WHERE clause for use in PostGIS SQL construction."
if table_prefix.endswith('.'):
table_prefix = backend.quote_name(table_prefix[:-1])+'.'
field_name = backend.quote_name(field_name)
table_prefix = quote_name(table_prefix[:-1])+'.'
field_name = quote_name(field_name)
# See if a PostGIS operator matches the lookup type first
try:

View File

@ -46,6 +46,11 @@ class GeometryField(GeoBackendField):
def get_internal_type(self):
return "NoField"
def db_type(self):
# Geometry columns are added by stored procedures, and thus should
# be None.
return None
def get_manipulator_field_objs(self):
"Using the WKTField (defined above) to be our manipulator."
return [WKTField]

View File

@ -1,6 +1,6 @@
import operator
from django.core.exceptions import ImproperlyConfigured
from django.db import backend
from django.db import connection
from django.db.models.query import Q, QuerySet, handle_legacy_orderlist, quote_only_if_word
from django.db.models.fields import FieldDoesNotExist
from django.utils.datastructures import SortedDict
@ -17,6 +17,8 @@ class GeoQ(Q):
class GeoQuerySet(QuerySet):
"Geographical-enabled QuerySet object."
quote_name = connection.ops.quote_name
#### Overloaded QuerySet Routines ####
def __init__(self, model=None):
super(GeoQuerySet, self).__init__(model=model)
@ -79,10 +81,10 @@ class GeoQuerySet(QuerySet):
# Add any additional SELECTs.
if self._select:
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), self.quote_name(s[0])) for s in self._select.items()])
# Start composing the body of the SQL statement.
sql = [" FROM", backend.quote_name(opts.db_table)]
sql = [" FROM", self.quote_name(opts.db_table)]
# Compose the join dictionary into SQL describing the joins.
if joins:
@ -115,15 +117,15 @@ class GeoQuerySet(QuerySet):
order = "ASC"
if "." in col_name:
table_prefix, col_name = col_name.split('.', 1)
table_prefix = backend.quote_name(table_prefix) + '.'
table_prefix = self.quote_name(table_prefix) + '.'
else:
# Use the database table as a column prefix if it wasn't given,
# and if the requested column isn't a custom SELECT.
if "." not in col_name and col_name not in (self._select or ()):
table_prefix = backend.quote_name(opts.db_table) + '.'
table_prefix = self.quote_name(opts.db_table) + '.'
else:
table_prefix = ''
order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order))
order_by.append('%s%s %s' % (table_prefix, self.quote_name(orderfield2column(col_name, opts)), order))
if order_by:
sql.append("ORDER BY " + ", ".join(order_by))
@ -142,8 +144,8 @@ class GeoQuerySet(QuerySet):
#### Methods specific to the GeoQuerySet ####
def _field_column(self, field):
return "%s.%s" % (backend.quote_name(self.model._meta.db_table),
backend.quote_name(field.column))
return "%s.%s" % (self.quote_name(self.model._meta.db_table),
self.quote_name(field.column))
def kml(self, field_name, precision=8):
"""Returns KML representation of the given field name in a `kml`
@ -174,7 +176,7 @@ class GeoQuerySet(QuerySet):
# override the geometry column returned from the database.
self._custom_select[field.column] = \
'(ST_Transform(%s, %s)) AS %s' % (self._field_column(field), srid,
backend.quote_name(field.column))
self.quote_name(field.column))
return self._clone()

View File

@ -1,6 +1,6 @@
# Getting what we need from ctypes
import re
from types import StringType, TupleType
from types import StringType, UnicodeType, TupleType
from ctypes import \
c_char_p, c_int, c_double, c_void_p, POINTER, \
byref, string_at, create_string_buffer
@ -84,6 +84,9 @@ class SpatialReference(object):
# Creating an initial empty string buffer.
buf = c_char_p('')
if isinstance(input, UnicodeType):
input = input.encode('ascii')
if isinstance(input, StringType):
# Is this an EPSG well known name?
m = self._epsg_regex.match(input)
@ -113,7 +116,7 @@ class SpatialReference(object):
# If the pointer is NULL, throw an exception.
if not srs:
raise SRSException, 'Could not create spatial reference from WKT!'
raise SRSException, 'Could not create spatial reference from WKT! (%s)' % input
else:
self._srs = srs
@ -304,6 +307,7 @@ class SpatialReference(object):
check_err(lgdal.OSRExportToProj4(self._srs, byref(w)))
return string_at(w)
@property
def proj4(self):
"Alias for proj()."
return self.proj

View File

@ -42,7 +42,7 @@ class SpatialRefSys(models.Model):
auth_name = models.CharField(maxlength=256)
auth_srid = models.IntegerField()
srtext = models.CharField(maxlength=2048)
proj4 = models.CharField(maxlength=2048, db_column='proj4text')
proj4text = models.CharField(maxlength=2048)
class Meta:
db_table = 'spatial_ref_sys'
@ -55,17 +55,17 @@ class SpatialRefSys(models.Model):
try:
self._srs = SpatialReference(self.srtext, 'wkt')
return
except:
except Exception, msg:
pass
# Trying the proj4 text next
try:
self._srs = SpatialReference(self.proj4, 'proj4')
self._srs = SpatialReference(self.proj4text, 'proj4')
return
except:
except Exception, msg:
pass
raise Exception, 'Could not get a OSR Spatial Reference.'
raise Exception, 'Could not get a OSR Spatial Reference: %s' % msg
else:
raise Exception, 'GDAL is not installed!'

View File

@ -25,7 +25,7 @@ def run(verbosity=1):
"Runs the tests that do not require geographic (GEOS, GDAL, etc.) models."
TextTestRunner(verbosity=verbosity).run(suite())
def run_tests(module_list, verbosity=1):
def run_tests(module_list, verbosity=1, interactive=True):
"""Run the tests that require creation of a spatial database. Does not
yet work on Windows platforms.

View File

@ -29,11 +29,11 @@ class SpatialRefSysTest(unittest.TestCase):
"Testing retrieval of SpatialRefSys model objects."
for sd in test_srs:
srs = SpatialRefSys.objects.get(srid=sd['srid'])
self.assertEqual(srs.srid, sd['srid'])
self.assertEqual(srs.auth_name, sd['auth_name'])
self.assertEqual(srs.auth_srid, sd['auth_srid'])
self.assertEqual(srs.srtext, sd['srtext'])
self.assertEqual(srs.proj4, sd['proj4'])
self.assertEqual(sd['srid'], srs.srid)
self.assertEqual(sd['auth_name'], srs.auth_name)
self.assertEqual(sd['auth_srid'], srs.auth_srid)
self.assertEqual(sd['srtext'], srs.srtext)
self.assertEqual(sd['proj4'], srs.proj4text)
def test02_osr(self):
"Testing getting OSR objects from SpatialRefSys model objects."
@ -46,11 +46,12 @@ class SpatialRefSysTest(unittest.TestCase):
# Testing the SpatialReference object directly.
srs = sr.srs
self.assertEqual(sd['proj4'], srs.proj)
self.assertEqual(sd['proj4'], srs.proj4)
self.assertEqual(sd['srtext'], srs.wkt)
def test03_ellipsoid(self):
"Testing the ellipsoid property."
return
for sd in test_srs:
# Getting the ellipsoid and precision parameters.
ellps1 = sd['ellipsoid']

View File

@ -1,6 +1,9 @@
from django.utils.translation import ngettext
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ungettext, ugettext as _
from django.utils.encoding import force_unicode
from django import template
from django.template import defaultfilters
from django.conf import settings
from datetime import date, timedelta
import re
register = template.Library()
@ -16,8 +19,8 @@ def ordinal(value):
return value
t = (_('th'), _('st'), _('nd'), _('rd'), _('th'), _('th'), _('th'), _('th'), _('th'), _('th'))
if value % 100 in (11, 12, 13): # special case
return "%d%s" % (value, t[0])
return '%d%s' % (value, t[value % 10])
return u"%d%s" % (value, t[0])
return u'%d%s' % (value, t[value % 10])
register.filter(ordinal)
def intcomma(value):
@ -25,8 +28,8 @@ def intcomma(value):
Converts an integer to a string containing commas every three digits.
For example, 3000 becomes '3,000' and 45000 becomes '45,000'.
"""
orig = str(value)
new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', str(value))
orig = force_unicode(value)
new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', orig)
if orig == new:
return new
else:
@ -44,13 +47,13 @@ def intword(value):
return value
if value < 1000000000:
new_value = value / 1000000.0
return ngettext('%(value).1f million', '%(value).1f million', new_value) % {'value': new_value}
return ungettext('%(value).1f million', '%(value).1f million', new_value) % {'value': new_value}
if value < 1000000000000:
new_value = value / 1000000000.0
return ngettext('%(value).1f billion', '%(value).1f billion', new_value) % {'value': new_value}
return ungettext('%(value).1f billion', '%(value).1f billion', new_value) % {'value': new_value}
if value < 1000000000000000:
new_value = value / 1000000000000.0
return ngettext('%(value).1f trillion', '%(value).1f trillion', new_value) % {'value': new_value}
return ungettext('%(value).1f trillion', '%(value).1f trillion', new_value) % {'value': new_value}
return value
register.filter(intword)
@ -67,3 +70,27 @@ def apnumber(value):
return value
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
register.filter(apnumber)
def naturalday(value, arg=None):
"""
For date values that are tomorrow, today or yesterday compared to
present day returns representing string. Otherwise, returns a string
formatted according to settings.DATE_FORMAT.
"""
try:
value = date(value.year, value.month, value.day)
except AttributeError:
# Passed value wasn't a date object
return value
except ValueError:
# Date arguments out of range
return value
delta = value - date.today()
if delta.days == 0:
return _(u'today')
elif delta.days == 1:
return _(u'tomorrow')
elif delta.days == -1:
return _(u'yesterday')
return defaultfilters.date(value, arg)
register.filter(naturalday)

Some files were not shown because too many files have changed in this diff Show More