1
0
mirror of https://github.com/django/django.git synced 2025-07-05 18:29:11 +00:00

[generic-auth] Merged to [4025]

git-svn-id: http://code.djangoproject.com/svn/django/branches/generic-auth@4026 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Joseph Kocherhans 2006-11-06 21:48:37 +00:00
parent 2f163ffe9a
commit d04abf372c
270 changed files with 14081 additions and 4483 deletions

33
AUTHORS
View File

@ -42,8 +42,10 @@ And here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS --
people who have submitted patches, reported bugs, added translations, helped people who have submitted patches, reported bugs, added translations, helped
answer newbie questions, and generally made Django that much better: answer newbie questions, and generally made Django that much better:
adurdin@gmail.com
akaihola akaihola
Andreas Andreas
ant9000@netwise.it
David Ascher <http://ascher.ca/> David Ascher <http://ascher.ca/>
Arthur <avandorp@gmail.com> Arthur <avandorp@gmail.com>
Jiri Barton Jiri Barton
@ -60,25 +62,36 @@ answer newbie questions, and generally made Django that much better:
Amit Chakradeo <http://amit.chakradeo.net/> Amit Chakradeo <http://amit.chakradeo.net/>
ChaosKCW ChaosKCW
Ian Clelland <clelland@gmail.com> Ian Clelland <clelland@gmail.com>
crankycoder@gmail.com
Matt Croydon <http://www.postneo.com/> Matt Croydon <http://www.postneo.com/>
dackze+django@gmail.com
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/> Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
Jason Davies (Esaj) <http://www.jasondavies.com/> Jason Davies (Esaj) <http://www.jasondavies.com/>
Alex Dedul Alex Dedul
deric@monowerks.com deric@monowerks.com
dne@mayonnaise.net dne@mayonnaise.net
Maximillian Dornseif <md@hudora.de>
dummy@habmalnefrage.de
Jeremy Dunck <http://dunck.us/> Jeremy Dunck <http://dunck.us/>
Andy Dustman <farcepest@gmail.com>
Clint Ecker Clint Ecker
Enrico <rico.bl@gmail.com>
favo@exoweb.net
gandalf@owca.info gandalf@owca.info
Baishampayan Ghose Baishampayan Ghose
martin.glueck@gmail.com martin.glueck@gmail.com
Simon Greenhill <dev@simon.net.nz> Simon Greenhill <dev@simon.net.nz>
Espen Grindhaug <http://grindhaug.org/> Espen Grindhaug <http://grindhaug.org/>
Brant Harris Brant Harris
Hawkeye
heckj@mac.com
Joel Heenan <joelh-django@planetjoel.com>
hipertracker@gmail.com hipertracker@gmail.com
Ian Holsman <http://feh.holsman.net/> Ian Holsman <http://feh.holsman.net/>
Kieran Holland <http://www.kieranholland.com> Kieran Holland <http://www.kieranholland.com>
Robert Rock Howard <http://djangomojo.com/> Robert Rock Howard <http://djangomojo.com/>
Jason Huggins <http://www.jrandolph.com/blog/> Jason Huggins <http://www.jrandolph.com/blog/>
Baurzhan Ismagulov <ibr@radix50.net>
jcrasta@gmail.com jcrasta@gmail.com
Michael Josephson <http://www.sdjournal.com/> Michael Josephson <http://www.sdjournal.com/>
jpellerin@gmail.com jpellerin@gmail.com
@ -87,26 +100,32 @@ answer newbie questions, and generally made Django that much better:
kilian <kilian.cavalotti@lip6.fr> kilian <kilian.cavalotti@lip6.fr>
Sune Kirkeby <http://ibofobi.dk/> Sune Kirkeby <http://ibofobi.dk/>
Cameron Knight (ckknight) Cameron Knight (ckknight)
Meir Kriheli <http://mksoft.co.il/>
Bruce Kroeze <http://coderseye.com/> Bruce Kroeze <http://coderseye.com/>
Joseph Kocherhans Joseph Kocherhans
konrad@gwu.edu konrad@gwu.edu
lakin.wecker@gmail.com lakin.wecker@gmail.com
Stuart Langridge <http://www.kryogenix.org/> Stuart Langridge <http://www.kryogenix.org/>
Eugene Lazutkin <http://lazutkin.com/blog/> Eugene Lazutkin <http://lazutkin.com/blog/>
Jeong-Min Lee <falsetru@gmail.com>
Christopher Lenz <http://www.cmlenz.net/> Christopher Lenz <http://www.cmlenz.net/>
lerouxb@gmail.com
limodou limodou
mattmcc
Martin Maney <http://www.chipy.org/Martin_Maney> Martin Maney <http://www.chipy.org/Martin_Maney>
masonsimon+django@gmail.com
Manuzhai Manuzhai
Petar Marić Petar Marić
mark@junklight.com mark@junklight.com
mattycakes@gmail.com mattycakes@gmail.com
Jason McBrayer <http://www.carcosa.net/jason/> Jason McBrayer <http://www.carcosa.net/jason/>
mccutchen@gmail.com
michael.mcewan@gmail.com michael.mcewan@gmail.com
mir@noris.de
mmarshall mmarshall
Eric Moritz <http://eric.themoritzfamily.com/> Eric Moritz <http://eric.themoritzfamily.com/>
Robin Munn <http://www.geekforgod.com/> Robin Munn <http://www.geekforgod.com/>
Nebojša Dorđević Nebojša Dorđević
Fraser Nevett <mail@nevett.org>
Sam Newman <http://www.magpiebrain.com/> Sam Newman <http://www.magpiebrain.com/>
Neal Norwitz <nnorwitz@google.com> Neal Norwitz <nnorwitz@google.com>
oggie rob <oz.robharvey@gmail.com> oggie rob <oz.robharvey@gmail.com>
@ -119,24 +138,36 @@ answer newbie questions, and generally made Django that much better:
plisk plisk
Daniel Poelzleithner <http://poelzi.org/> Daniel Poelzleithner <http://poelzi.org/>
J. Rademaker J. Rademaker
Michael Radziej <mir@noris.de>
ramiro
Brian Ray <http://brianray.chipy.org/> Brian Ray <http://brianray.chipy.org/>
rhettg@gmail.com rhettg@gmail.com
Oliver Rutherfurd <http://rutherfurd.net/> Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/> Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
David Schein David Schein
serbaut@gmail.com
Pete Shinners <pete@shinners.org>
SmileyChris <smileychris@gmail.com>
sopel sopel
Thomas Steinacher <tom@eggdrop.ch>
Radek Švarz <http://www.svarz.cz/translate/> Radek Švarz <http://www.svarz.cz/translate/>
Swaroop C H <http://www.swaroopch.info> Swaroop C H <http://www.swaroopch.info>
Aaron Swartz <http://www.aaronsw.com/> Aaron Swartz <http://www.aaronsw.com/>
Tyson Tate <tyson@fallingbullets.com>
Tom Tobin Tom Tobin
Tom Insam Tom Insam
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/> Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
Karen Tracey <graybark@bellsouth.net>
Amit Upadhyay Amit Upadhyay
Geert Vanderkelen Geert Vanderkelen
Milton Waddams Milton Waddams
wam-djangobug@wamber.net
Dan Watson <http://theidioteque.net/>
Rachel Willmer <http://www.willmer.com/kb/> Rachel Willmer <http://www.willmer.com/kb/>
Gary Wilson <gary.wilson@gmail.com>
wojtek wojtek
ye7cakf02@sneakemail.com ye7cakf02@sneakemail.com
ymasuda@ethercube.com
Cheng Zhang Cheng Zhang
A big THANK YOU goes to: A big THANK YOU goes to:

8
MANIFEST.in Normal file
View File

@ -0,0 +1,8 @@
include AUTHORS
include INSTALL
include LICENSE
recursive-include django/conf/locale *
recursive-include django/contrib/admin/templates
recursive-include django/contrib/admin/media
recursive-include django/contrib/comments/templates
recursive-include django/contrib/sitemaps/templates

4
README
View File

@ -25,10 +25,10 @@ http://code.djangoproject.com/newticket
To get more help: To get more help:
* Join the #django channel on irc.freenode.net. Lots of helpful people * Join the #django channel on irc.freenode.net. Lots of helpful people
hang out there. Read the archives at http://loglibrary.com/179 . hang out there. Read the archives at http://simon.bofh.ms/logger/django/ .
* Join the django-users mailing list, or read the archives, at * Join the django-users mailing list, or read the archives, at
http://groups-beta.google.com/group/django-users. http://groups.google.com/group/django-users.
To contribute to Django: To contribute to Django:

View File

@ -11,15 +11,25 @@ def compile_messages():
elif os.path.isdir('locale'): elif os.path.isdir('locale'):
basedir = os.path.abspath('locale') basedir = os.path.abspath('locale')
else: else:
print "this script should be run from the django svn tree or your project or app tree" print "This script should be run from the Django SVN tree or your project or app tree."
sys.exit(1) sys.exit(1)
for (dirpath, dirnames, filenames) in os.walk(basedir): for dirpath, dirnames, filenames in os.walk(basedir):
for f in filenames: for f in filenames:
if f.endswith('.po'): if f.endswith('.po'):
sys.stderr.write('processing file %s in %s\n' % (f, dirpath)) sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
pf = os.path.splitext(os.path.join(dirpath, f))[0] pf = os.path.splitext(os.path.join(dirpath, f))[0]
cmd = 'msgfmt -o "%s.mo" "%s.po"' % (pf, pf) # Store the names of the .mo and .po files in an environment
# variable, rather than doing a string replacement into the
# command, so that we can take advantage of shell quoting, to
# quote any malicious characters/escaping.
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
os.environ['djangocompilemo'] = pf + '.mo'
os.environ['djangocompilepo'] = pf + '.po'
if sys.platform == 'win32': # Different shell-variable syntax
cmd = 'msgfmt -o "%djangocompilemo%" "%djangocompilepo%"'
else:
cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd) os.system(cmd)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,16 +1,17 @@
"Daily cleanup file" """
Daily cleanup job.
Can be run as a cronjob to clean out old data from the database (only expired
sessions at the moment).
"""
from django.db import backend, connection, transaction from django.db import backend, connection, transaction
DOCUMENTATION_DIRECTORY = '/home/html/documentation/'
def clean_up(): def clean_up():
# Clean up old database records # Clean up old database records
cursor = connection.cursor() cursor = connection.cursor()
cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \ cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \
(backend.quote_name('core_sessions'), backend.quote_name('expire_date'))) (backend.quote_name('django_session'), backend.quote_name('expire_date')))
cursor.execute("DELETE FROM %s WHERE %s < NOW() - INTERVAL '1 week'" % \
(backend.quote_name('registration_challenges'), backend.quote_name('request_date')))
transaction.commit_unless_managed() transaction.commit_unless_managed()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -77,7 +77,7 @@ class Settings(object):
self.SETTINGS_MODULE = settings_module self.SETTINGS_MODULE = settings_module
try: try:
mod = __import__(self.SETTINGS_MODULE, '', '', ['']) mod = __import__(self.SETTINGS_MODULE, {}, {}, [''])
except ImportError, e: except ImportError, e:
raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e) raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
@ -97,7 +97,7 @@ class Settings(object):
new_installed_apps = [] new_installed_apps = []
for app in self.INSTALLED_APPS: for app in self.INSTALLED_APPS:
if app.endswith('.*'): if app.endswith('.*'):
appdir = os.path.dirname(__import__(app[:-2], '', '', ['']).__file__) appdir = os.path.dirname(__import__(app[:-2], {}, {}, ['']).__file__)
for d in os.listdir(appdir): for d in os.listdir(appdir):
if d.isalpha() and os.path.isdir(os.path.join(appdir, d)): if d.isalpha() and os.path.isdir(os.path.join(appdir, d)):
new_installed_apps.append('%s.%s' % (app[:-2], d)) new_installed_apps.append('%s.%s' % (app[:-2], d))

View File

@ -46,6 +46,7 @@ LANGUAGES = (
('en', gettext_noop('English')), ('en', gettext_noop('English')),
('es', gettext_noop('Spanish')), ('es', gettext_noop('Spanish')),
('es_AR', gettext_noop('Argentinean Spanish')), ('es_AR', gettext_noop('Argentinean Spanish')),
('fi', gettext_noop('Finnish')),
('fr', gettext_noop('French')), ('fr', gettext_noop('French')),
('gl', gettext_noop('Galician')), ('gl', gettext_noop('Galician')),
('hu', gettext_noop('Hungarian')), ('hu', gettext_noop('Hungarian')),
@ -55,6 +56,7 @@ LANGUAGES = (
('ja', gettext_noop('Japanese')), ('ja', gettext_noop('Japanese')),
('nl', gettext_noop('Dutch')), ('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')), ('no', gettext_noop('Norwegian')),
('pl', gettext_noop('Polish')),
('pt-br', gettext_noop('Brazilian')), ('pt-br', gettext_noop('Brazilian')),
('ro', gettext_noop('Romanian')), ('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')), ('ru', gettext_noop('Russian')),
@ -63,6 +65,7 @@ LANGUAGES = (
('sr', gettext_noop('Serbian')), ('sr', gettext_noop('Serbian')),
('sv', gettext_noop('Swedish')), ('sv', gettext_noop('Swedish')),
('ta', gettext_noop('Tamil')), ('ta', gettext_noop('Tamil')),
('tr', gettext_noop('Turkish')),
('uk', gettext_noop('Ukrainian')), ('uk', gettext_noop('Ukrainian')),
('zh-cn', gettext_noop('Simplified Chinese')), ('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', gettext_noop('Traditional Chinese')), ('zh-tw', gettext_noop('Traditional Chinese')),
@ -221,10 +224,6 @@ YEAR_MONTH_FORMAT = 'F Y'
# http://www.djangoproject.com/documentation/templates/#now # http://www.djangoproject.com/documentation/templates/#now
MONTH_DAY_FORMAT = 'F j' MONTH_DAY_FORMAT = 'F j'
# Whether to enable Psyco, which optimizes Python code. Requires Psyco.
# http://psyco.sourceforge.net/
ENABLE_PSYCO = False
# Do you want to manage transactions manually? # Do you want to manage transactions manually?
# Hint: you really don't! # Hint: you really don't!
TRANSACTIONS_MANAGED = False TRANSACTIONS_MANAGED = False
@ -252,6 +251,7 @@ MIDDLEWARE_CLASSES = (
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want. SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want.
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks). SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie. SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only).
SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request. SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request.
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser. SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser.
@ -270,6 +270,10 @@ CACHE_MIDDLEWARE_KEY_PREFIX = ''
COMMENTS_ALLOW_PROFANITIES = False COMMENTS_ALLOW_PROFANITIES = False
# The profanities that will trigger a validation error in the
# 'hasNoProfanities' validator. All of these should be in lowercase.
PROFANITIES_LIST = ('asshat', 'asshead', 'asshole', 'cunt', 'fuck', 'gook', 'nigger', 'shit')
# The group ID that designates which users are banned. # The group ID that designates which users are banned.
# Set to None if you're not using it. # Set to None if you're not using it.
COMMENTS_BANNED_USERS_GROUP = None COMMENTS_BANNED_USERS_GROUP = None
@ -295,3 +299,14 @@ BANNED_IPS = ()
################## ##################
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
###########
# TESTING #
###########
# The name of the method to use to invoke the test suite
TEST_RUNNER = 'django.test.simple.run_tests'
# The name of the database to use for testing purposes.
# If None, a name of 'test_' + DATABASE_NAME will be assumed
TEST_DATABASE_NAME = None

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,110 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2006-08-05 15:27+0300\n"
"Last-Translator: Antti Kaihola <akaihola@ambitone.com>\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 "Mahdolliset %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Valitse kaikki"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Lisää uusi"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Poista"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Valitut %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Valitse vasemmalta ja napsauta "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Tyhjennä kaikki"
#: 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 ""
"Tammikuu Helmikuu Maaliskuu Huhtikuu Toukokuu Kesäkuu Heinäkuu Elokuu "
"Syyskuu Lokakuu Marraskuu Joulukuu"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Sunnuntai Maanantai Tiistai Keskiviikko Torstai Perjantai Lauantai"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "S M T K T P L"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "Nyt"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "Kello"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "Valitse kellonaika"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "24"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "06"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "12"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "Peruuta"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "Tänään"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "Kalenteri"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "Eilen"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Huomenna"

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django 1.0\n" "Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: Django-users Japan <django-ja@googlegroups.com>\n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-02 23:06+0900\n" "POT-Creation-Date: 2006-10-06 00:30+0900\n"
"PO-Revision-Date: 2006-05-08 13:39+0900\n" "PO-Revision-Date: 2006-05-08 13:39+0900\n"
"Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n" "Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n"
"Language-Team: Japanese <django-ja@googlegroups.com>\n" "Language-Team: Japanese <django-ja@googlegroups.com>\n"
@ -61,50 +61,58 @@ msgstr "選択してクリック"
msgid "Clear all" msgid "Clear all"
msgstr "全てクリア" msgstr "全てクリア"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "表示"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "非表示"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now" msgid "Now"
msgstr "現在" msgstr "現在"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock" msgid "Clock"
msgstr "時計" msgstr "時計"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time" msgid "Choose a time"
msgstr "時間を選択" msgstr "時間を選択"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight" msgid "Midnight"
msgstr "夜中" msgstr "夜中"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m." msgid "6 a.m."
msgstr "午前 6 時" msgstr "午前 6 時"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon" msgid "Noon"
msgstr "正午" msgstr "正午"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel" msgid "Cancel"
msgstr "キャンセル" msgstr "キャンセル"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today" msgid "Today"
msgstr "今日" msgstr "今日"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar" msgid "Calendar"
msgstr "カレンダー" msgstr "カレンダー"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday" msgid "Yesterday"
msgstr "昨日" msgstr "昨日"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow" msgid "Tomorrow"
msgstr "明日" msgstr "明日"

View File

@ -264,7 +264,7 @@ msgstr "Bare POST er tillatt"
#: contrib/comments/views/comments.py:193 #: contrib/comments/views/comments.py:193
#: contrib/comments/views/comments.py:284 #: contrib/comments/views/comments.py:284
msgid "One or more of the required fields wasn't submitted" msgid "One or more of the required fields wasn't submitted"
msgstr "En eller flere av feltene som er krevd ble ikke sendt." msgstr "En eller flere av feltene som er krevd ble ikke sendt."
#: contrib/comments/views/comments.py:197 #: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286 #: contrib/comments/views/comments.py:286
@ -371,35 +371,32 @@ msgid "All"
msgstr "Alle" msgstr "Alle"
#: contrib/admin/filterspecs.py:109 #: contrib/admin/filterspecs.py:109
#, fuzzy
msgid "Any date" msgid "Any date"
msgstr "Alle datoer" msgstr "Når som helst"
#: contrib/admin/filterspecs.py:110 #: contrib/admin/filterspecs.py:110
#, fuzzy
msgid "Today" msgid "Today"
msgstr "Mondag" msgstr "I dag"
#: contrib/admin/filterspecs.py:113 #: contrib/admin/filterspecs.py:113
msgid "Past 7 days" msgid "Past 7 days"
msgstr "" msgstr "Siste 7 dager"
#: contrib/admin/filterspecs.py:115 #: contrib/admin/filterspecs.py:115
msgid "This month" msgid "This month"
msgstr "" msgstr "Denne måneden"
#: contrib/admin/filterspecs.py:117 #: contrib/admin/filterspecs.py:117
msgid "This year" msgid "This year"
msgstr "" msgstr "I år"
#: contrib/admin/filterspecs.py:143 #: contrib/admin/filterspecs.py:143
msgid "Yes" msgid "Yes"
msgstr "" msgstr "Ja"
#: contrib/admin/filterspecs.py:143 #: contrib/admin/filterspecs.py:143
#, fuzzy
msgid "No" msgid "No"
msgstr "Nov." msgstr "Nei"
#: contrib/admin/filterspecs.py:150 #: contrib/admin/filterspecs.py:150
msgid "Unknown" msgid "Unknown"
@ -443,11 +440,13 @@ msgid ""
"Please enter a correct username and password. Note that both fields are case-" "Please enter a correct username and password. Note that both fields are case-"
"sensitive." "sensitive."
msgstr "" msgstr ""
"Vær snill å angi korrekt brukernavn og passord. La merke til at små og "
"store bokstaver er betraktet ulik."
#: contrib/admin/views/decorators.py:23 #: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25 #: contrib/admin/templates/admin/login.html:25
msgid "Log in" msgid "Log in"
msgstr "Log inn" msgstr "Logg inn"
#: contrib/admin/views/decorators.py:61 #: contrib/admin/views/decorators.py:61
msgid "" msgid ""
@ -473,12 +472,11 @@ msgstr "Brukernavnet kan ikke inneholde '@'"
#: contrib/admin/views/decorators.py:84 #: contrib/admin/views/decorators.py:84
#, python-format #, python-format
msgid "Your e-mail address is not your username. Try '%s' instead." msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr "Epost adressen din er ikke brukernavnet ditt, prøv '%s' i stede." msgstr "E-post adressen din er ikke brukernavnet ditt, prøv '%s' i stede."
#: contrib/admin/views/main.py:226 #: contrib/admin/views/main.py:226
#, fuzzy
msgid "Site administration" msgid "Site administration"
msgstr "Django administrasjon" msgstr "Nettsted administrasjon"
#: contrib/admin/views/main.py:260 #: contrib/admin/views/main.py:260
#, python-format #, python-format
@ -502,7 +500,7 @@ msgstr "Ny %s"
#: contrib/admin/views/main.py:336 #: contrib/admin/views/main.py:336
#, python-format #, python-format
msgid "Added %s." msgid "Added %s."
msgstr "La til %s" msgstr "Lagt til %s"
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338 #: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
#: contrib/admin/views/main.py:340 #: contrib/admin/views/main.py:340
@ -559,7 +557,7 @@ msgid "Are you sure?"
msgstr "Er du sikker?" msgstr "Er du sikker?"
#: contrib/admin/views/main.py:533 #: contrib/admin/views/main.py:533
#, fuzzy, python-format #, python-format
msgid "Change history: %s" msgid "Change history: %s"
msgstr "Endre historien: %s" msgstr "Endre historien: %s"
@ -580,7 +578,6 @@ msgid "Integer"
msgstr "Heltall" msgstr "Heltall"
#: contrib/admin/views/doc.py:278 #: contrib/admin/views/doc.py:278
#, fuzzy
msgid "Boolean (Either True or False)" msgid "Boolean (Either True or False)"
msgstr "Boolean (Enten \"True\" eller \"False\")" msgstr "Boolean (Enten \"True\" eller \"False\")"
@ -603,7 +600,7 @@ msgstr "Dato/tid"
#: contrib/admin/views/doc.py:283 #: contrib/admin/views/doc.py:283
msgid "E-mail address" msgid "E-mail address"
msgstr "Epost adresse" msgstr "E-post adresse"
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287 #: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
msgid "File path" msgid "File path"
@ -614,13 +611,12 @@ msgid "Decimal number"
msgstr "Desimal tall" msgstr "Desimal tall"
#: contrib/admin/views/doc.py:291 #: contrib/admin/views/doc.py:291
#, fuzzy
msgid "Boolean (Either True, False or None)" msgid "Boolean (Either True, False or None)"
msgstr "Boolean (enten \"True\", \"False\" eller \"None\")" msgstr "Boolean (enten \"True\", \"False\" eller \"None\")"
#: contrib/admin/views/doc.py:292 #: contrib/admin/views/doc.py:292
msgid "Relation to parent model" msgid "Relation to parent model"
msgstr "" msgstr "Relasjon til forelder modell"
#: contrib/admin/views/doc.py:293 #: contrib/admin/views/doc.py:293
msgid "Phone number" msgid "Phone number"
@ -636,7 +632,7 @@ msgstr "Tid"
#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7 #: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
msgid "URL" msgid "URL"
msgstr "Internettadresse" msgstr "URL"
#: contrib/admin/views/doc.py:301 #: contrib/admin/views/doc.py:301
msgid "U.S. state (two uppercase letters)" msgid "U.S. state (two uppercase letters)"
@ -756,12 +752,12 @@ msgstr "Fant ikke siden"
#: contrib/admin/templates/admin/404.html:10 #: contrib/admin/templates/admin/404.html:10
msgid "We're sorry, but the requested page could not be found." msgid "We're sorry, but the requested page could not be found."
msgstr "Beklager, men siden du spør etter finnest ikke." msgstr "Beklager, men siden du spør etter finnes ikke."
#: contrib/admin/templates/admin/index.html:17 #: contrib/admin/templates/admin/index.html:17
#, python-format #, python-format
msgid "Models available in the %(name)s application." msgid "Models available in the %(name)s application."
msgstr "" msgstr "Modeller fra applikasjonen %(name)s."
#: contrib/admin/templates/admin/index.html:28 #: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15 #: contrib/admin/templates/admin/change_form.html:15
@ -813,7 +809,7 @@ msgid ""
"objects, but your account doesn't have permission to delete the following " "objects, but your account doesn't have permission to delete the following "
"types of objects:" "types of objects:"
msgstr "" msgstr ""
"Vist du sletter %(object_name)s '%(object)s' vill du også slette relaterte " "Hivs du sletter %(object_name)s '%(object)s' vil du også slette relaterte "
"objekter, men du har ikke tillatelse til å slette de følgende objektene:" "objekter, men du har ikke tillatelse til å slette de følgende objektene:"
#: contrib/admin/templates/admin/delete_confirmation.html:21 #: contrib/admin/templates/admin/delete_confirmation.html:21
@ -836,11 +832,11 @@ msgstr "Av %(title)s "
#: contrib/admin/templates/admin/search_form.html:8 #: contrib/admin/templates/admin/search_form.html:8
msgid "Go" msgid "Go"
msgstr "" msgstr ""
#: contrib/admin/templates/admin/change_form.html:21 #: contrib/admin/templates/admin/change_form.html:21
msgid "View on site" msgid "View on site"
msgstr "Vis på siden" msgstr "Vis på nettsted"
#: contrib/admin/templates/admin/change_form.html:30 #: contrib/admin/templates/admin/change_form.html:30
msgid "Please correct the error below." msgid "Please correct the error below."
@ -900,12 +896,12 @@ msgid ""
"Forgotten your password? Enter your e-mail address below, and we'll reset " "Forgotten your password? Enter your e-mail address below, and we'll reset "
"your password and e-mail the new one to you." "your password and e-mail the new one to you."
msgstr "" msgstr ""
"Har du glemt passordet ditt? Skriv inn epost adressen din under, så sender " "Har du glemt passordet ditt? Skriv inn e-post adressen din under, så sender "
"vi deg et nytt passord via epost." "vi deg et nytt passord via e-post."
#: contrib/admin/templates/registration/password_reset_form.html:16 #: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:" msgid "E-mail address:"
msgstr "Epost adresse:" msgstr "E-post adresse:"
#: contrib/admin/templates/registration/password_reset_form.html:16 #: contrib/admin/templates/registration/password_reset_form.html:16
msgid "Reset my password" msgid "Reset my password"
@ -917,7 +913,7 @@ msgstr "Takk for å bruke tid på internett siden i dag."
#: contrib/admin/templates/registration/logged_out.html:10 #: contrib/admin/templates/registration/logged_out.html:10
msgid "Log in again" msgid "Log in again"
msgstr "Log inn igjen" msgstr "Logg inn igjen"
#: contrib/admin/templates/registration/password_reset_done.html:6 #: contrib/admin/templates/registration/password_reset_done.html:6
#: contrib/admin/templates/registration/password_reset_done.html:10 #: contrib/admin/templates/registration/password_reset_done.html:10
@ -929,7 +925,7 @@ msgid ""
"We've e-mailed a new password to the e-mail address you submitted. You " "We've e-mailed a new password to the e-mail address you submitted. You "
"should be receiving it shortly." "should be receiving it shortly."
msgstr "" msgstr ""
"Vi sender deg et nytt passord til epost adressen du oppgav. Du villmotta det " "Vi sender deg et nytt passord til e-post adressen du oppgav. Du villmotta det "
"snart." "snart."
#: contrib/admin/templates/registration/password_change_form.html:12 #: contrib/admin/templates/registration/password_change_form.html:12
@ -959,7 +955,7 @@ msgstr "Endre passord"
#: contrib/admin/templates/registration/password_reset_email.html:2 #: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset" msgid "You're receiving this e-mail because you requested a password reset"
msgstr "" msgstr ""
"Du har mottatt denne epost-en fordi du ba om å tilbakestille passordet ditt" "Du har mottatt denne e-posten fordi du ba om å tilbakestille passordet ditt"
#: contrib/admin/templates/registration/password_reset_email.html:3 #: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format #, python-format
@ -1036,10 +1032,9 @@ msgid "Edit this object (current window)"
msgstr "Endre dette objektet (åpnes i dette vinduet)" msgstr "Endre dette objektet (åpnes i dette vinduet)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26 #: contrib/admin/templates/admin_doc/bookmarklets.html:26
#, fuzzy
msgid "Jumps to the admin page for pages that represent a single object." msgid "Jumps to the admin page for pages that represent a single object."
msgstr "" msgstr ""
"Hopp til administrasjonsiden for siden som representerer et enkelt objekt." "Hopp til administrasjonsiden for sidene som representerer et enkelt objekt."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28 #: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)" msgid "Edit this object (new window)"
@ -1051,21 +1046,19 @@ msgstr "Samme som over, men åpner administrasjonsiden i et nytt vindu."
#: contrib/admin/templates/widget/date_time.html:3 #: contrib/admin/templates/widget/date_time.html:3
msgid "Date:" msgid "Date:"
msgstr "" msgstr "Dato:"
#: contrib/admin/templates/widget/date_time.html:4 #: contrib/admin/templates/widget/date_time.html:4
#, fuzzy
msgid "Time:" msgid "Time:"
msgstr "Tid" msgstr "Tid:"
#: contrib/admin/templates/widget/file.html:2 #: contrib/admin/templates/widget/file.html:2
msgid "Currently:" msgid "Currently:"
msgstr "" msgstr "Nå:"
#: contrib/admin/templates/widget/file.html:3 #: contrib/admin/templates/widget/file.html:3
#, fuzzy
msgid "Change:" msgid "Change:"
msgstr "Endre" msgstr "Endre:"
#: contrib/redirects/models.py:7 #: contrib/redirects/models.py:7
msgid "redirect from" msgid "redirect from"
@ -1126,7 +1119,7 @@ msgid ""
"Example: 'flatpages/contact_page'. If this isn't provided, the system will " "Example: 'flatpages/contact_page'. If this isn't provided, the system will "
"use 'flatpages/default'." "use 'flatpages/default'."
msgstr "" msgstr ""
"Eksempel: 'flatfiler/kontakt_side'. Vist denne ikke denne er gitt, vill " "Eksempel: 'flatfiler/kontakt_side'. Hvis denne ikke denne er gitt, vill "
"'flatfiles/default' bli brukt." "'flatfiles/default' bli brukt."
#: contrib/flatpages/models.py:14 #: contrib/flatpages/models.py:14
@ -1136,7 +1129,7 @@ msgstr "registrering kreves"
#: contrib/flatpages/models.py:14 #: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page." msgid "If this is checked, only logged-in users will be able to view the page."
msgstr "" msgstr ""
"Vist denne er krysset av er det bare brukere som er logget inn som kan se " "Hvis denne er krysset av er det bare brukere som er logget inn som kan se "
"siden." "siden."
#: contrib/flatpages/models.py:18 #: contrib/flatpages/models.py:18
@ -1156,24 +1149,20 @@ msgid "codename"
msgstr "kodenavn" msgstr "kodenavn"
#: contrib/auth/models.py:17 #: contrib/auth/models.py:17
#, fuzzy
msgid "permission" msgid "permission"
msgstr "Rettighet" msgstr "rettighet"
#: contrib/auth/models.py:18 contrib/auth/models.py:27 #: contrib/auth/models.py:18 contrib/auth/models.py:27
#, fuzzy
msgid "permissions" msgid "permissions"
msgstr "Rettigheter" msgstr "rettigheter"
#: contrib/auth/models.py:29 #: contrib/auth/models.py:29
#, fuzzy
msgid "group" msgid "group"
msgstr "Gruppe" msgstr "gruppe"
#: contrib/auth/models.py:30 contrib/auth/models.py:65 #: contrib/auth/models.py:30 contrib/auth/models.py:65
#, fuzzy
msgid "groups" msgid "groups"
msgstr "Grupper" msgstr "grupper"
#: contrib/auth/models.py:55 #: contrib/auth/models.py:55
msgid "username" msgid "username"
@ -1205,7 +1194,7 @@ msgstr "administrasjons status"
#: contrib/auth/models.py:60 #: contrib/auth/models.py:60
msgid "Designates whether the user can log into this admin site." msgid "Designates whether the user can log into this admin site."
msgstr "Bestemmer om brukeren kan logge inn på denne administrasjons siden." msgstr "Bestemmer om brukeren kan logge inn på dette administrasjons sted."
#: contrib/auth/models.py:61 #: contrib/auth/models.py:61
msgid "active" msgid "active"
@ -1217,7 +1206,7 @@ msgstr "super bruker"
#: contrib/auth/models.py:63 #: contrib/auth/models.py:63
msgid "last login" msgid "last login"
msgstr "liste logg inn" msgstr "siste logg inn"
#: contrib/auth/models.py:64 #: contrib/auth/models.py:64
msgid "date joined" msgid "date joined"
@ -1232,19 +1221,16 @@ msgstr ""
"tilgang til gruppene han/hun er i." "tilgang til gruppene han/hun er i."
#: contrib/auth/models.py:67 #: contrib/auth/models.py:67
#, fuzzy
msgid "user permissions" msgid "user permissions"
msgstr "Rettigheter" msgstr "Rettigheter"
#: contrib/auth/models.py:70 #: contrib/auth/models.py:70
#, fuzzy
msgid "user" msgid "user"
msgstr "Bruker" msgstr "bruker"
#: contrib/auth/models.py:71 #: contrib/auth/models.py:71
#, fuzzy
msgid "users" msgid "users"
msgstr "Brukere" msgstr "brukere"
#: contrib/auth/models.py:76 #: contrib/auth/models.py:76
msgid "Personal info" msgid "Personal info"
@ -1263,9 +1249,8 @@ msgid "Groups"
msgstr "Grupper" msgstr "Grupper"
#: contrib/auth/models.py:219 #: contrib/auth/models.py:219
#, fuzzy
msgid "message" msgid "message"
msgstr "Meldinger" msgstr "Melding"
#: contrib/auth/forms.py:30 #: contrib/auth/forms.py:30
msgid "" msgid ""
@ -1274,9 +1259,8 @@ msgid ""
msgstr "" msgstr ""
#: contrib/contenttypes/models.py:25 #: contrib/contenttypes/models.py:25
#, fuzzy
msgid "python model class name" msgid "python model class name"
msgstr "python modul navn" msgstr "python modell klasse navn"
#: contrib/contenttypes/models.py:28 #: contrib/contenttypes/models.py:28
msgid "content type" msgid "content type"
@ -1312,23 +1296,23 @@ msgstr "domene navn"
#: contrib/sites/models.py:11 #: contrib/sites/models.py:11
msgid "display name" msgid "display name"
msgstr "vist navn" msgstr "vise navn"
#: contrib/sites/models.py:15 #: contrib/sites/models.py:15
msgid "site" msgid "site"
msgstr "side" msgstr "nettsted"
#: contrib/sites/models.py:16 #: contrib/sites/models.py:16
msgid "sites" msgid "sites"
msgstr "sider" msgstr "nettsteder"
#: utils/translation.py:360 #: utils/translation.py:360
msgid "DATE_FORMAT" msgid "DATE_FORMAT"
msgstr "j. M U" msgstr "j. M Y"
#: utils/translation.py:361 #: utils/translation.py:361
msgid "DATETIME_FORMAT" msgid "DATETIME_FORMAT"
msgstr "j. M U - h:i" msgstr "j. M Y - h:i"
#: utils/translation.py:362 #: utils/translation.py:362
msgid "TIME_FORMAT" msgid "TIME_FORMAT"
@ -1336,7 +1320,7 @@ msgstr "h:i"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Monday" msgid "Monday"
msgstr "Mondag" msgstr "Mandag"
#: utils/dates.py:6 #: utils/dates.py:6
msgid "Tuesday" msgid "Tuesday"
@ -1411,54 +1395,52 @@ msgid "December"
msgstr "Desember" msgstr "Desember"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy
msgid "jan" msgid "jan"
msgstr "og" msgstr "jan"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "feb" msgid "feb"
msgstr "" msgstr "feb"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "mar" msgid "mar"
msgstr "" msgstr "mar"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "apr" msgid "apr"
msgstr "" msgstr "apr"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy
msgid "may" msgid "may"
msgstr "Mai" msgstr "mai"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "jun" msgid "jun"
msgstr "" msgstr "jun"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "jul" msgid "jul"
msgstr "" msgstr "jul"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "aug" msgid "aug"
msgstr "" msgstr "aug"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "sep" msgid "sep"
msgstr "" msgstr "sep"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "oct" msgid "oct"
msgstr "" msgstr "okt"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "nov" msgid "nov"
msgstr "" msgstr "nov"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "dec" msgid "dec"
msgstr "" msgstr "des"
#: utils/dates.py:27 #: utils/dates.py:27
msgid "Jan." msgid "Jan."
@ -1466,7 +1448,7 @@ msgstr "Jan."
#: utils/dates.py:27 #: utils/dates.py:27
msgid "Feb." msgid "Feb."
msgstr "Fef." msgstr "Feb."
#: utils/dates.py:28 #: utils/dates.py:28
msgid "Aug." msgid "Aug."
@ -1491,40 +1473,38 @@ msgstr "Des."
#: utils/timesince.py:12 #: utils/timesince.py:12
msgid "year" msgid "year"
msgid_plural "years" msgid_plural "years"
msgstr[0] "" msgstr[0] "år"
msgstr[1] "" msgstr[1] "år"
#: utils/timesince.py:13 #: utils/timesince.py:13
msgid "month" msgid "month"
msgid_plural "months" msgid_plural "months"
msgstr[0] "" msgstr[0] "måned"
msgstr[1] "" msgstr[1] "måndeder"
#: utils/timesince.py:14 #: utils/timesince.py:14
msgid "week" msgid "week"
msgid_plural "weeks" msgid_plural "weeks"
msgstr[0] "" msgstr[0] "uke"
msgstr[1] "" msgstr[1] "uker"
#: utils/timesince.py:15 #: utils/timesince.py:15
#, fuzzy
msgid "day" msgid "day"
msgid_plural "days" msgid_plural "days"
msgstr[0] "Mai" msgstr[0] "dag"
msgstr[1] "Mai" msgstr[1] "dager"
#: utils/timesince.py:16 #: utils/timesince.py:16
msgid "hour" msgid "hour"
msgid_plural "hours" msgid_plural "hours"
msgstr[0] "" msgstr[0] "time"
msgstr[1] "" msgstr[1] "timer"
#: utils/timesince.py:17 #: utils/timesince.py:17
#, fuzzy
msgid "minute" msgid "minute"
msgid_plural "minutes" msgid_plural "minutes"
msgstr[0] "side" msgstr[0] "minutt"
msgstr[1] "side" msgstr[1] "minutter"
#: conf/global_settings.py:37 #: conf/global_settings.py:37
msgid "Bengali" msgid "Bengali"
@ -1548,7 +1528,7 @@ msgstr "Tysk"
#: conf/global_settings.py:42 #: conf/global_settings.py:42
msgid "Greek" msgid "Greek"
msgstr "" msgstr "Gresk"
#: conf/global_settings.py:43 #: conf/global_settings.py:43
msgid "English" msgid "English"
@ -1568,11 +1548,11 @@ msgstr "Galisisk"
#: conf/global_settings.py:47 #: conf/global_settings.py:47
msgid "Hungarian" msgid "Hungarian"
msgstr "" msgstr "Ungarsk"
#: conf/global_settings.py:48 #: conf/global_settings.py:48
msgid "Hebrew" msgid "Hebrew"
msgstr "" msgstr "Hebraiske"
#: conf/global_settings.py:49 #: conf/global_settings.py:49
msgid "Icelandic" msgid "Icelandic"
@ -1584,11 +1564,11 @@ msgstr "Italiensk"
#: conf/global_settings.py:51 #: conf/global_settings.py:51
msgid "Japanese" msgid "Japanese"
msgstr "" msgstr "Japansk"
#: conf/global_settings.py:52 #: conf/global_settings.py:52
msgid "Dutch" msgid "Dutch"
msgstr "" msgstr "Nederlandsk"
#: conf/global_settings.py:53 #: conf/global_settings.py:53
msgid "Norwegian" msgid "Norwegian"
@ -1600,7 +1580,7 @@ msgstr "Brasiliansk"
#: conf/global_settings.py:55 #: conf/global_settings.py:55
msgid "Romanian" msgid "Romanian"
msgstr "Romansk" msgstr "Rumensk"
#: conf/global_settings.py:56 #: conf/global_settings.py:56
msgid "Russian" msgid "Russian"
@ -1611,9 +1591,8 @@ msgid "Slovak"
msgstr "Slovakisk" msgstr "Slovakisk"
#: conf/global_settings.py:58 #: conf/global_settings.py:58
#, fuzzy
msgid "Slovenian" msgid "Slovenian"
msgstr "Slovakisk" msgstr "Slovensk"
#: conf/global_settings.py:59 #: conf/global_settings.py:59
msgid "Serbian" msgid "Serbian"
@ -1624,9 +1603,8 @@ msgid "Swedish"
msgstr "Svensk" msgstr "Svensk"
#: conf/global_settings.py:61 #: conf/global_settings.py:61
#, fuzzy
msgid "Ukrainian" msgid "Ukrainian"
msgstr "Brasiliansk" msgstr "Ukrainsk"
#: conf/global_settings.py:62 #: conf/global_settings.py:62
msgid "Simplified Chinese" msgid "Simplified Chinese"
@ -1634,14 +1612,13 @@ msgstr "Simplifisert Kinesisk"
#: conf/global_settings.py:63 #: conf/global_settings.py:63
msgid "Traditional Chinese" msgid "Traditional Chinese"
msgstr "" msgstr "Tradisjonell Kinesisk"
#: core/validators.py:60 #: core/validators.py:60
msgid "This value must contain only letters, numbers and underscores." msgid "This value must contain only letters, numbers and underscores."
msgstr "Dette feltet må bare inneholde bokstaver, nummer og understreker." msgstr "Dette feltet må bare inneholde bokstaver, nummer og understreker."
#: core/validators.py:64 #: core/validators.py:64
#, fuzzy
msgid "" msgid ""
"This value must contain only letters, numbers, underscores, dashes or " "This value must contain only letters, numbers, underscores, dashes or "
"slashes." "slashes."
@ -1651,7 +1628,7 @@ msgstr ""
#: core/validators.py:72 #: core/validators.py:72
msgid "Uppercase letters are not allowed here." msgid "Uppercase letters are not allowed here."
msgstr "Tor skrift er ikke tillatt her." msgstr "Stor bokstaver er ikke tillatt her."
#: core/validators.py:76 #: core/validators.py:76
msgid "Lowercase letters are not allowed here." msgid "Lowercase letters are not allowed here."
@ -1687,19 +1664,19 @@ msgstr "Skriv inn et helt nummer."
#: core/validators.py:120 #: core/validators.py:120
msgid "Only alphabetical characters are allowed here." msgid "Only alphabetical characters are allowed here."
msgstr "Bare alfabetiske bokstaber er tillatt her." msgstr "Bare alfabetiske bokstaver er tillatt her."
#: core/validators.py:124 #: core/validators.py:124
msgid "Enter a valid date in YYYY-MM-DD format." msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "Skriv inn en dato i ÅÅÅÅ-MM-DD formatet." msgstr "Skriv inn en dato i ÅÅÅÅ-MM-DD format."
#: core/validators.py:128 #: core/validators.py:128
msgid "Enter a valid time in HH:MM format." msgid "Enter a valid time in HH:MM format."
msgstr "Skriv inn tiden i TT:MM formatet." msgstr "Skriv inn tiden i TT:MM format."
#: core/validators.py:132 db/models/fields/__init__.py:468 #: core/validators.py:132 db/models/fields/__init__.py:468
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "Skriv inn dato og tid i ÅÅÅÅ-MM-DD TT:MM formatet." msgstr "Skriv inn dato og tid i ÅÅÅÅ-MM-DD TT:MM format."
#: core/validators.py:136 #: core/validators.py:136
msgid "Enter a valid e-mail address." msgid "Enter a valid e-mail address."
@ -1722,7 +1699,7 @@ msgstr "Internettadressen %s peker ikke til et godkjent bilde."
#, python-format #, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr "" msgstr ""
"Telefon nummeret må være i XXX-XXX-XXXX formatet. \"%s\" er ikke godkjent." "Telefon nummeret må være i XXX-XXX-XXXX format. \"%s\" er ikke godkjent."
#: core/validators.py:167 #: core/validators.py:167
#, python-format #, python-format
@ -1731,7 +1708,7 @@ msgstr "Internettadressen %s peker ikke til en godkjent QuickTime film."
#: core/validators.py:171 #: core/validators.py:171
msgid "A valid URL is required." msgid "A valid URL is required."
msgstr "En godkjent internettadresse er påbudt." msgstr "En godkjent internettadresse er påkrevd."
#: core/validators.py:185 #: core/validators.py:185
#, python-format #, python-format
@ -1739,7 +1716,7 @@ msgid ""
"Valid HTML is required. Specific errors are:\n" "Valid HTML is required. Specific errors are:\n"
"%s" "%s"
msgstr "" msgstr ""
"Godkjent HTML er påbudt. Feilene var:\n" "Godkjent HTML er påkrevd. Feilene var:\n"
"%s" "%s"
#: core/validators.py:192 #: core/validators.py:192
@ -1750,7 +1727,7 @@ msgstr "Ikke godkjent XML: %s"
#: core/validators.py:202 #: core/validators.py:202
#, python-format #, python-format
msgid "Invalid URL: %s" msgid "Invalid URL: %s"
msgstr "Ikke godkjent internettadresse: %s" msgstr "Ikke godkjent URL: %s"
#: core/validators.py:206 core/validators.py:208 #: core/validators.py:206 core/validators.py:208
#, python-format #, python-format
@ -1759,7 +1736,7 @@ msgstr "Internettadresse fører til en side som ikke virker."
#: core/validators.py:214 #: core/validators.py:214
msgid "Enter a valid U.S. state abbreviation." msgid "Enter a valid U.S. state abbreviation."
msgstr "Skriv inn en godkjent amerikansk stats forkortelse." msgstr "Skriv inn en godkjent amerikansk delstat forkortelse."
#: core/validators.py:229 #: core/validators.py:229
#, python-format #, python-format
@ -1771,7 +1748,7 @@ msgstr[1] "Pass munnen din! Ordene %s er ikke tillatt her."
#: core/validators.py:236 #: core/validators.py:236
#, python-format #, python-format
msgid "This field must match the '%s' field." msgid "This field must match the '%s' field."
msgstr "Dette felte må være det samme som i '%s' feltet." msgstr "Dette feltet må være det samme som i '%s' feltet."
#: core/validators.py:255 #: core/validators.py:255
msgid "Please enter something for at least one field." msgid "Please enter something for at least one field."
@ -1784,12 +1761,12 @@ msgstr "Vennligst skriv inn noe i begge felta, eller la dem stå blanke."
#: core/validators.py:282 #: core/validators.py:282
#, python-format #, python-format
msgid "This field must be given if %(field)s is %(value)s" msgid "This field must be given if %(field)s is %(value)s"
msgstr "Dette feltet må bare brukes vist %(field)s er lik %(value)s" msgstr "Dette feltet må bare brukes hvis %(field)s er lik %(value)s"
#: core/validators.py:294 #: core/validators.py:294
#, python-format #, python-format
msgid "This field must be given if %(field)s is not %(value)s" msgid "This field must be given if %(field)s is not %(value)s"
msgstr "Dette feltet må bare brukes vist %(field)s ikke er lik %(value)s" msgstr "Dette feltet må bare brukes hvis %(field)s ikke er lik %(value)s"
#: core/validators.py:313 #: core/validators.py:313
msgid "Duplicate values are not allowed." msgid "Duplicate values are not allowed."
@ -1824,13 +1801,13 @@ msgstr[1] "Skriv inn et desimal tall med maksimum %s tall bak komma. "
#, python-format #, python-format
msgid "Make sure your uploaded file is at least %s bytes big." msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "" msgstr ""
"Er du sikker på at fila du prøver å laste opp er minimum %s bytes stor?" "Vær sikker på at fila du prøver å laste opp er minimum %s bytes stor."
#: core/validators.py:363 #: core/validators.py:363
#, python-format #, python-format
msgid "Make sure your uploaded file is at most %s bytes big." msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "" msgstr ""
"Er du sikker på at fila du prøver å laste opp er maksimum %s bytes stor?" "Vær sikker på at fila du prøver å laste opp er maksimum %s bytes stor."
#: core/validators.py:376 #: core/validators.py:376
msgid "The format for this field is wrong." msgid "The format for this field is wrong."
@ -1850,7 +1827,7 @@ msgstr "Klarte ikke å motta noe fra %s."
msgid "" msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "" msgstr ""
"Tnternettadressen %(url)s returnerte en ikke godkjent Content-Type '%" "Internettadressen %(url)s returnerte en ikke godkjent Content-Type '%"
"(contenttype)s'." "(contenttype)s'."
#: core/validators.py:462 #: core/validators.py:462
@ -1859,7 +1836,7 @@ msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
"\"%(start)s\".)" "\"%(start)s\".)"
msgstr "" msgstr ""
"Vennligst lukk taggen %(tag)s på linje %(line)s. (Linja starer med \"%(start)" "Vennligst lukk taggen %(tag)s på linje %(line)s. (Linjen starer med \"%(start)"
"s\".)" "s\".)"
#: core/validators.py:466 #: core/validators.py:466
@ -1868,7 +1845,7 @@ msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line " "Some text starting on line %(line)s is not allowed in that context. (Line "
"starts with \"%(start)s\".)" "starts with \"%(start)s\".)"
msgstr "" msgstr ""
"Noe av teksten som starter på linje %(line)s er ikke tillatt. (Linja starter " "Noe av teksten som starter på linje %(line)s er ikke tillatt. (Linjen starter "
"med \"%(start)s\".)" "med \"%(start)s\".)"
#: core/validators.py:471 #: core/validators.py:471
@ -1877,7 +1854,7 @@ msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
"(start)s\".)" "(start)s\".)"
msgstr "" msgstr ""
"\"%(attr)s\" på linje %(line)s er ikke en godkjent tillegg. (Linja starter " "\"%(attr)s\" på linje %(line)s er ikke en godkjent tillegg. (Linjen starter "
"med \"%(start)s\".)" "med \"%(start)s\".)"
#: core/validators.py:476 #: core/validators.py:476
@ -1886,7 +1863,7 @@ msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
"(start)s\".)" "(start)s\".)"
msgstr "" msgstr ""
"\"<%(tag)s>\" på linje %(line)s er ikke en godkjent tag. (linja starter med " "\"<%(tag)s>\" på linje %(line)s er ikke en godkjent tag. (linjen starter med "
"\"%(start)s\".)" "\"%(start)s\".)"
#: core/validators.py:480 #: core/validators.py:480
@ -1895,7 +1872,7 @@ msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line " "A tag on line %(line)s is missing one or more required attributes. (Line "
"starts with \"%(start)s\".)" "starts with \"%(start)s\".)"
msgstr "" msgstr ""
"En tag på linje %(line)s mangler en av de påbydte tillegga. (linja starter " "En tag på linje %(line)s mangler en av de påkrevde attributtene. (linjen starter "
"med \"%(start)s\".)" "med \"%(start)s\".)"
#: core/validators.py:485 #: core/validators.py:485
@ -1904,13 +1881,13 @@ msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
"starts with \"%(start)s\".)" "starts with \"%(start)s\".)"
msgstr "" msgstr ""
"\"%(attr)s\" tillegg på linje $(line)s har en ikke godkjent verdi. (Linja " "\"%(attr)s\" tillegg på linje $(line)s har en ikke godkjent verdi. (Linjen "
"starter med \"%(start)s\".)" "starter med \"%(start)s\".)"
#: db/models/manipulators.py:302 #: db/models/manipulators.py:302
#, fuzzy, python-format #, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s." msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr "$(optname)s med %(fieldname)s finnes allerede." msgstr "%(object)s med %(type)s finnes allerede for angitt %(field)s."
#: db/models/fields/__init__.py:40 #: db/models/fields/__init__.py:40
#, python-format #, python-format
@ -1924,37 +1901,31 @@ msgid "This field is required."
msgstr "Dette feltet er påkrevd." msgstr "Dette feltet er påkrevd."
#: db/models/fields/__init__.py:337 #: db/models/fields/__init__.py:337
#, fuzzy
msgid "This value must be an integer." msgid "This value must be an integer."
msgstr "Denne verdien må være 'power' av %s." msgstr "Denne verdien må være et heltall."
#: db/models/fields/__init__.py:369 #: db/models/fields/__init__.py:369
#, fuzzy
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Denne verdien må være 'power' av %s." msgstr "Denne verdien må være enten \"True\" eller \"False\"."
#: db/models/fields/__init__.py:385 #: db/models/fields/__init__.py:385
#, fuzzy
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "Dette feltet er feil." msgstr "Dette feltet kan ikke være null/tom."
#: db/models/fields/__init__.py:562 #: db/models/fields/__init__.py:562
#, fuzzy
msgid "Enter a valid filename." msgid "Enter a valid filename."
msgstr "Skriv inn en godkjent e-post adresse." msgstr "Skriv inn et godkjent fil navn."
#: db/models/fields/related.py:43 #: db/models/fields/related.py:43
#, fuzzy, python-format #, python-format
msgid "Please enter a valid %s." msgid "Please enter a valid %s."
msgstr "Vennligst skriv inn en godkjent IP adresse." msgstr "Vennligst skriv inn en/et gyldig %s."
#: db/models/fields/related.py:579 #: db/models/fields/related.py:579
#, fuzzy
msgid "Separate multiple IDs with commas." msgid "Separate multiple IDs with commas."
msgstr "Separer Id-ene med kommaer." msgstr "Separer Id-ene med kommaer."
#: db/models/fields/related.py:581 #: db/models/fields/related.py:581
#, fuzzy
msgid "" msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr "" msgstr ""
@ -1965,14 +1936,14 @@ msgstr ""
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural "" msgid_plural ""
"Please enter valid %(self)s IDs. The values %(value)r are invalid." "Please enter valid %(self)s IDs. The values %(value)r are invalid."
msgstr[0] "" msgstr[0] "Skriv inn gyldige %(self)s ID-er. Verdien %(value)r er ikke gyldig."
msgstr[1] "" msgstr[1] "Skriv inn gyldige %(self)s ID-er. Verdiene %(value)r er ikke gyldige."
#: forms/__init__.py:380 #: forms/__init__.py:380
#, fuzzy, python-format #, python-format
msgid "Ensure your text is less than %s character." msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters." msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Sjekk at teksten er kortere enn %s bokstaver" msgstr[0] "Sjekk at teksten er kortere enn %s bokstav"
msgstr[1] "Sjekk at teksten er kortere enn %s bokstaver" msgstr[1] "Sjekk at teksten er kortere enn %s bokstaver"
#: forms/__init__.py:385 #: forms/__init__.py:385
@ -1982,7 +1953,7 @@ msgstr "Det er ikke tillatt med flere linjer her."
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 #: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
#, python-format #, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s." msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Velg et av valga; '%(data)s' er ikke i %(choices)s." msgstr "Velg et gyldig valg; '%(data)s' er ikke i %(choices)s."
#: forms/__init__.py:645 #: forms/__init__.py:645
msgid "The submitted file is empty." msgid "The submitted file is empty."
@ -2002,7 +1973,7 @@ msgstr "Skriv inn et heltall mellom 0 og 32767."
#: template/defaultfilters.py:379 #: template/defaultfilters.py:379
msgid "yes,no,maybe" msgid "yes,no,maybe"
msgstr "" msgstr "ja,nei,kanskje"
#, fuzzy #, fuzzy
#~ msgid "Comments" #~ msgid "Comments"

View File

@ -61,6 +61,15 @@ msgstr "Søndag Mandag Tirsdag Onsdag Torsdag Fredag Lørdag"
msgid "S M T W T F S" msgid "S M T W T F S"
msgstr "S M T O T F L" msgstr "S M T O T F L"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "Vis"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "Skjul"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now" msgid "Now"
@ -80,7 +89,7 @@ msgstr "24.00"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m." msgid "6 a.m."
msgstr "18.00" msgstr "06.00"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon" msgid "Noon"

View File

@ -126,12 +126,10 @@ msgid "approved by staff"
msgstr "zaakceptowano" msgstr "zaakceptowano"
#: contrib/comments/models.py:176 #: contrib/comments/models.py:176
#, fuzzy
msgid "free comment" msgid "free comment"
msgstr "wolny komentarz" msgstr "wolny komentarz"
#: contrib/comments/models.py:177 #: contrib/comments/models.py:177
#, fuzzy
msgid "free comments" msgid "free comments"
msgstr "wolne komentarze" msgstr "wolne komentarze"
@ -144,7 +142,6 @@ msgid "score date"
msgstr "data przyznania punktów" msgstr "data przyznania punktów"
#: contrib/comments/models.py:237 #: contrib/comments/models.py:237
#, fuzzy
msgid "karma score" msgid "karma score"
msgstr "ilość punktów" msgstr "ilość punktów"
@ -243,6 +240,9 @@ msgid ""
"\n" "\n"
"%(text)s" "%(text)s"
msgstr "" msgstr ""
"Ten komentarze został dodany przez użytkownika::\n"
"\n"
"%(text)s"
#: contrib/comments/views/comments.py:189 #: contrib/comments/views/comments.py:189
#: contrib/comments/views/comments.py:280 #: contrib/comments/views/comments.py:280
@ -257,19 +257,20 @@ msgstr "Jedno lub więcej wymaganych pól nie zostało wypełnionych"
#: contrib/comments/views/comments.py:197 #: contrib/comments/views/comments.py:197
#: contrib/comments/views/comments.py:286 #: contrib/comments/views/comments.py:286
msgid "Somebody tampered with the comment form (security violation)" msgid "Somebody tampered with the comment form (security violation)"
msgstr "" msgstr "Ktoś próbował obejść zabezpieczenia formularza komentarzy"
#: contrib/comments/views/comments.py:207 #: contrib/comments/views/comments.py:207
#: contrib/comments/views/comments.py:292 #: contrib/comments/views/comments.py:292
msgid "" msgid ""
"The comment form had an invalid 'target' parameter -- the object ID was " "The comment form had an invalid 'target' parameter -- the object ID was "
"invalid" "invalid"
msgstr "" msgstr "Formularz komentarza miał niepoprawny parametr 'target' -- ID obiektu było "
"niepoprawne"
#: contrib/comments/views/comments.py:257 #: contrib/comments/views/comments.py:257
#: contrib/comments/views/comments.py:321 #: contrib/comments/views/comments.py:321
msgid "The comment form didn't provide either 'preview' or 'post'" msgid "The comment form didn't provide either 'preview' or 'post'"
msgstr "" msgstr "Formularz komentarza nie zapewnił obiektów 'preview' ani 'post'"
#: contrib/comments/templates/comments/form.html:6 #: contrib/comments/templates/comments/form.html:6
#: contrib/comments/templates/comments/form.html:8 #: contrib/comments/templates/comments/form.html:8
@ -600,7 +601,7 @@ msgstr "Wartość logiczna (True, False, None - prawda, fałsz lub nic)"
#: contrib/admin/views/doc.py:292 #: contrib/admin/views/doc.py:292
msgid "Relation to parent model" msgid "Relation to parent model"
msgstr "" msgstr "Relacja do modelu rodzica"
#: contrib/admin/views/doc.py:293 #: contrib/admin/views/doc.py:293
msgid "Phone number" msgid "Phone number"
@ -794,6 +795,9 @@ msgid ""
"objects, but your account doesn't have permission to delete the following " "objects, but your account doesn't have permission to delete the following "
"types of objects:" "types of objects:"
msgstr "" msgstr ""
"Skasowanie %(object_name)s '%(object)s' spowoduje kasację zależnych "
"obiektów, lecz twoje uprawnienia nie pozwalają na usunięcie następujących "
"typów obiektów:"
#: contrib/admin/templates/admin/delete_confirmation.html:21 #: contrib/admin/templates/admin/delete_confirmation.html:21
#, python-format #, python-format
@ -801,6 +805,8 @@ msgid ""
"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of " "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
"the following related items will be deleted:" "the following related items will be deleted:"
msgstr "" msgstr ""
"Czy chcesz skasować %(object_name)s \"%(object)s\"? Wszystkie "
"zależne obiekty zostaną skasowane:"
#: contrib/admin/templates/admin/delete_confirmation.html:26 #: contrib/admin/templates/admin/delete_confirmation.html:26
msgid "Yes, I'm sure" msgid "Yes, I'm sure"
@ -820,11 +826,10 @@ msgid "View on site"
msgstr "Pokaż na stronie" msgstr "Pokaż na stronie"
#: contrib/admin/templates/admin/change_form.html:30 #: contrib/admin/templates/admin/change_form.html:30
#, fuzzy
msgid "Please correct the error below." msgid "Please correct the error below."
msgid_plural "Please correct the errors below." msgid_plural "Please correct the errors below."
msgstr[0] "Proszę popraw poniższy błąd" msgstr[0] "Proszę popraw poniższy błąd"
msgstr[1] "Proszę popraw poniższy błąd" msgstr[1] "Proszę popraw poniższe błędy"
#: contrib/admin/templates/admin/change_form.html:48 #: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering" msgid "Ordering"
@ -965,11 +970,11 @@ msgstr "Zespół %(site_name)s"
#: contrib/admin/templates/admin_doc/bookmarklets.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Bookmarklets" msgid "Bookmarklets"
msgstr "" msgstr "Zakładki"
#: contrib/admin/templates/admin_doc/bookmarklets.html:5 #: contrib/admin/templates/admin_doc/bookmarklets.html:5
msgid "Documentation bookmarklets" msgid "Documentation bookmarklets"
msgstr "" msgstr "Zakładki Dokumentacji"
#: contrib/admin/templates/admin_doc/bookmarklets.html:9 #: contrib/admin/templates/admin_doc/bookmarklets.html:9
msgid "" msgid ""
@ -1094,6 +1099,8 @@ msgid ""
"Example: 'flatpages/contact_page'. If this isn't provided, the system will " "Example: 'flatpages/contact_page'. If this isn't provided, the system will "
"use 'flatpages/default'." "use 'flatpages/default'."
msgstr "" msgstr ""
"Przykład: 'flatpages/contact_page'. Jeżeli nie podane system użyje "
"'flatpages/default'."
#: contrib/flatpages/models.py:14 #: contrib/flatpages/models.py:14
msgid "registration required" msgid "registration required"
@ -1105,11 +1112,11 @@ msgstr "Jeżeli zaznaczone - tylko zalogowani użytkownicy będą mogli zobaczy
#: contrib/flatpages/models.py:18 #: contrib/flatpages/models.py:18
msgid "flat page" msgid "flat page"
msgstr "" msgstr "strona statyczna"
#: contrib/flatpages/models.py:19 #: contrib/flatpages/models.py:19
msgid "flat pages" msgid "flat pages"
msgstr "" msgstr "strony statyczne"
#: contrib/auth/models.py:13 contrib/auth/models.py:26 #: contrib/auth/models.py:13 contrib/auth/models.py:26
msgid "name" msgid "name"
@ -1117,7 +1124,7 @@ msgstr "nazwa"
#: contrib/auth/models.py:15 #: contrib/auth/models.py:15
msgid "codename" msgid "codename"
msgstr "" msgstr "nazwa kodowa"
#: contrib/auth/models.py:17 #: contrib/auth/models.py:17
msgid "permission" msgid "permission"
@ -1161,11 +1168,11 @@ msgstr "Użyj '[algo]$[salt]$[hexdigest]'"
#: contrib/auth/models.py:60 #: contrib/auth/models.py:60
msgid "staff status" msgid "staff status"
msgstr "stan w zespole" msgstr "w zespole"
#: contrib/auth/models.py:60 #: contrib/auth/models.py:60
msgid "Designates whether the user can log into this admin site." msgid "Designates whether the user can log into this admin site."
msgstr "Oznaczy czy użytkownik może zalogować się do panelu admina." msgstr "Oznacza czy użytkownik może zalogować się do panelu admina."
#: contrib/auth/models.py:61 #: contrib/auth/models.py:61
msgid "active" msgid "active"
@ -1195,15 +1202,14 @@ msgstr ""
msgid "user permissions" msgid "user permissions"
msgstr "uprawnienia użytkownika" msgstr "uprawnienia użytkownika"
#kurwa
#: contrib/auth/models.py:70 #: contrib/auth/models.py:70
#, fuzzy
msgid "user" msgid "user"
msgstr "Użytkownik" msgstr "użytkownik"
#: contrib/auth/models.py:71 #: contrib/auth/models.py:71
#, fuzzy
msgid "users" msgid "users"
msgstr "Uzytkownicy" msgstr "ytkownicy"
#: contrib/auth/models.py:76 #: contrib/auth/models.py:76
msgid "Personal info" msgid "Personal info"
@ -1222,7 +1228,6 @@ msgid "Groups"
msgstr "Grupy" msgstr "Grupy"
#: contrib/auth/models.py:219 #: contrib/auth/models.py:219
#, fuzzy
msgid "message" msgid "message"
msgstr "wiadomość" msgstr "wiadomość"
@ -1371,7 +1376,6 @@ msgid "December"
msgstr "Grudzień" msgstr "Grudzień"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy
msgid "jan" msgid "jan"
msgstr "sty" msgstr "sty"
@ -1472,11 +1476,10 @@ msgstr[0] "dzień"
msgstr[1] "dni" msgstr[1] "dni"
#: utils/timesince.py:16 #: utils/timesince.py:16
#, fuzzy
msgid "hour" msgid "hour"
msgid_plural "hours" msgid_plural "hours"
msgstr[0] "godzina" msgstr[0] "godzina"
msgstr[1] "godzina" msgstr[1] "godzin"
#: utils/timesince.py:17 #: utils/timesince.py:17
msgid "minute" msgid "minute"
@ -1569,7 +1572,6 @@ msgid "Slovak"
msgstr "Słowacki" msgstr "Słowacki"
#: conf/global_settings.py:58 #: conf/global_settings.py:58
#, fuzzy
msgid "Slovenian" msgid "Slovenian"
msgstr "Słowacki" msgstr "Słowacki"
@ -1582,9 +1584,8 @@ msgid "Swedish"
msgstr "Szwedzki" msgstr "Szwedzki"
#: conf/global_settings.py:61 #: conf/global_settings.py:61
#, fuzzy
msgid "Ukrainian" msgid "Ukrainian"
msgstr "Brazylijski" msgstr "Ukraiński"
#: conf/global_settings.py:62 #: conf/global_settings.py:62
msgid "Simplified Chinese" msgid "Simplified Chinese"
@ -1715,14 +1716,14 @@ msgstr "Odnośnik %s jest nieprawidłowy."
#: core/validators.py:214 #: core/validators.py:214
msgid "Enter a valid U.S. state abbreviation." msgid "Enter a valid U.S. state abbreviation."
msgstr "Wpisz poprawny kod stanu U.S." msgstr "Wpisz poprawny kod stanu U.S.A."
#: core/validators.py:229 #: core/validators.py:229
#, fuzzy, python-format #, python-format
msgid "Watch your mouth! The word %s is not allowed here." msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Nie wolno przeklinać! Słowo %s jest niedozwolone." msgstr[0] "Nie wolno przeklinać! Słowo %s jest niedozwolone."
msgstr[1] "Nie wolno przeklinać! Słowo %s jest niedozwolone." msgstr[1] "Nie wolno przeklinać! Słowa %s są niedozwolone."
#: core/validators.py:236 #: core/validators.py:236
#, python-format #, python-format
@ -1745,11 +1746,11 @@ msgstr "To pole musi być uzupełnione jeśli %(field)s jest %(value)s"
#: core/validators.py:294 #: core/validators.py:294
#, python-format #, python-format
msgid "This field must be given if %(field)s is not %(value)s" msgid "This field must be given if %(field)s is not %(value)s"
msgstr "" msgstr "To pole musi być wypełnione jeżeli %(field)s nie jest %(value)s"
#: core/validators.py:313 #: core/validators.py:313
msgid "Duplicate values are not allowed." msgid "Duplicate values are not allowed."
msgstr "" msgstr "Duplikaty są niedozwolone."
#: core/validators.py:336 #: core/validators.py:336
#, python-format #, python-format
@ -1761,20 +1762,20 @@ msgid "Please enter a valid decimal number."
msgstr "Proszę wpisać poprawną liczbę dziesiętną." msgstr "Proszę wpisać poprawną liczbę dziesiętną."
#: core/validators.py:349 #: core/validators.py:349
#, fuzzy, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s total digit." msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural "" msgid_plural ""
"Please enter a valid decimal number with at most %s total digits." "Please enter a valid decimal number with at most %s total digits."
msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną." msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfry."
msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną." msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfr."
#: core/validators.py:352 #: core/validators.py:352
#, fuzzy, python-format #, python-format
msgid "Please enter a valid decimal number with at most %s decimal place." msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural "" msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places." "Please enter a valid decimal number with at most %s decimal places."
msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną." msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną z dokładnością do %s miejsca po przecinku."
msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną." msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną z dokładnością do %s miejsc po przecinku."
#: core/validators.py:362 #: core/validators.py:362
#, python-format #, python-format
@ -1797,13 +1798,14 @@ msgstr "To pole jest nieprawidłowe."
#: core/validators.py:426 #: core/validators.py:426
#, python-format #, python-format
msgid "Could not retrieve anything from %s." msgid "Could not retrieve anything from %s."
msgstr "Nie można otrzymać nic z %s." msgstr "Nie można nic pobrać z %s."
#: core/validators.py:429 #: core/validators.py:429
#, python-format #, python-format
msgid "" msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr "" msgstr ""
"URL %(url)s zwrócił niepoprawny Content-Type header '%(contenttype)s'."
#: core/validators.py:462 #: core/validators.py:462
@ -1866,17 +1868,15 @@ msgstr "To pole jest wymagane"
#: db/models/fields/__init__.py:337 #: db/models/fields/__init__.py:337
msgid "This value must be an integer." msgid "This value must be an integer."
msgstr "" msgstr "Ta wartość musi być liczbą całkowitą"
#: db/models/fields/__init__.py:369 #: db/models/fields/__init__.py:369
#, fuzzy
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Wartość logiczna (True, False - prawda lub fałsz)" msgstr "Ta wartość musi być logiczna (True, False - prawda lub fałsz)."
#: db/models/fields/__init__.py:385 #: db/models/fields/__init__.py:385
#, fuzzy
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "To pole jest nieprawidłowe." msgstr "To pole nie może być puste."
#: db/models/fields/__init__.py:562 #: db/models/fields/__init__.py:562
msgid "Enter a valid filename." msgid "Enter a valid filename."
@ -1888,12 +1888,10 @@ msgid "Please enter a valid %s."
msgstr "Proszę wpisać poprawne %s." msgstr "Proszę wpisać poprawne %s."
#: db/models/fields/related.py:579 #: db/models/fields/related.py:579
#, fuzzy
msgid "Separate multiple IDs with commas." msgid "Separate multiple IDs with commas."
msgstr "Oddziel kilka pól ID przecinkami." msgstr "Oddziel kilka pól ID przecinkami."
#: db/models/fields/related.py:581 #: db/models/fields/related.py:581
#, fuzzy
msgid "" msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr "" msgstr ""
@ -1909,11 +1907,11 @@ msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: forms/__init__.py:380 #: forms/__init__.py:380
#, fuzzy, python-format #, python-format
msgid "Ensure your text is less than %s character." msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters." msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Upewnij się, że jest mniej niż %s znaków." msgstr[0] "Upewnij się, że tekst ma mniej niż %s znak."
msgstr[1] "Upewnij się, że jest mniej niż %s znaków." msgstr[1] "Upewnij się, że tekst ma mniej niż %s znaków."
#: forms/__init__.py:385 #: forms/__init__.py:385
msgid "Line breaks are not allowed here." msgid "Line breaks are not allowed here."

View File

@ -2,14 +2,15 @@
# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# João Marcus Christ <joaoma@gmail.com>, 2006. # João Marcus Christ <joaoma@gmail.com>, 2006.
# Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: django\n" "Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:11+0200\n" "POT-Creation-Date: 2006-05-16 10:11+0200\n"
"PO-Revision-Date: 2006-01-23 19:54-0200\n" "PO-Revision-Date: 2006-11-01 17:45-0300\n"
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n" "Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
"Language-Team: Português do Brasil <pt-br@li.org>\n" "Language-Team: Português do Brasil <pt-br@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -86,12 +87,12 @@ msgid ""
"removed\" message will be displayed instead." "removed\" message will be displayed instead."
msgstr "" msgstr ""
"Selecione esta opção se o comentário é inapropriado. Uma mensagem \"Este " "Selecione esta opção se o comentário é inapropriado. Uma mensagem \"Este "
"comentário foi removido\" será mostrada no lugar." "comentário foi removido\" a mensagem será mostrada no lugar."
#: contrib/comments/models.py:91 #: contrib/comments/models.py:91
#, fuzzy #, fuzzy
msgid "comments" msgid "comments"
msgstr "comentário" msgstr "comentários"
#: contrib/comments/models.py:131 contrib/comments/models.py:207 #: contrib/comments/models.py:131 contrib/comments/models.py:207
msgid "Content object" msgid "Content object"
@ -150,7 +151,7 @@ msgstr "Pontuação de Karma"
#: contrib/comments/models.py:238 #: contrib/comments/models.py:238
#, fuzzy #, fuzzy
msgid "karma scores" msgid "karma scores"
msgstr "Pontuação de Karma" msgstr "Pontuações de Karma"
#: contrib/comments/models.py:242 #: contrib/comments/models.py:242
#, python-format #, python-format
@ -170,17 +171,17 @@ msgstr ""
#: contrib/comments/models.py:265 #: contrib/comments/models.py:265
msgid "flag date" msgid "flag date"
msgstr "marca de data" msgstr "flag de data"
#: contrib/comments/models.py:268 #: contrib/comments/models.py:268
#, fuzzy #, fuzzy
msgid "user flag" msgid "user flag"
msgstr "Flag de usuário" msgstr "flag de usuário"
#: contrib/comments/models.py:269 #: contrib/comments/models.py:269
#, fuzzy #, fuzzy
msgid "user flags" msgid "user flags"
msgstr "Flags de usuário" msgstr "flags de usuário"
#: contrib/comments/models.py:273 #: contrib/comments/models.py:273
#, python-format #, python-format
@ -189,22 +190,22 @@ msgstr "Flag por %r"
#: contrib/comments/models.py:278 #: contrib/comments/models.py:278
msgid "deletion date" msgid "deletion date"
msgstr "data de apagamento" msgstr "data de exclusão"
#: contrib/comments/models.py:280 #: contrib/comments/models.py:280
#, fuzzy #, fuzzy
msgid "moderator deletion" msgid "moderator deletion"
msgstr "Apagamento feito por moderador" msgstr "Exclusão feita pelo moderador"
#: contrib/comments/models.py:281 #: contrib/comments/models.py:281
#, fuzzy #, fuzzy
msgid "moderator deletions" msgid "moderator deletions"
msgstr "Apagamentos feitos por moderador" msgstr "Exclusões feitas pelo moderador"
#: contrib/comments/models.py:285 #: contrib/comments/models.py:285
#, python-format #, python-format
msgid "Moderator deletion by %r" msgid "Moderator deletion by %r"
msgstr "Apagamento feito pelo moderador %r" msgstr "Exclusao feita pelo moderador %r"
#: contrib/comments/views/karma.py:19 #: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote" msgid "Anonymous users cannot vote"
@ -237,12 +238,12 @@ msgid_plural ""
"\n" "\n"
"%(text)s" "%(text)s"
msgstr[0] "" msgstr[0] ""
"Este comentário foi feito por um usuário esboço:\n" "Este comentário foi feito por um usuário que postou menos de %(count)s "
"\n" "comentário:\n"
"%(text)s" "%(text)s"
msgstr[1] "" msgstr[1] ""
"Este comentário foi feito por um usuário esboço:\n" "Este comentário foi feito por um usuário que postou menos de %(count)s "
"\n" "comentários:\n"
"%(text)s" "%(text)s"
#: contrib/comments/views/comments.py:117 #: contrib/comments/views/comments.py:117
@ -252,7 +253,7 @@ msgid ""
"\n" "\n"
"%(text)s" "%(text)s"
msgstr "" msgstr ""
"Este comentário foi feito por um usuário esboço:\n" "Este comentário foi feito por um usuário incompleto:\n"
"\n" "\n"
"%(text)s" "%(text)s"
@ -299,7 +300,7 @@ msgstr "Senha:"
#: contrib/comments/templates/comments/form.html:6 #: contrib/comments/templates/comments/form.html:6
#, fuzzy #, fuzzy
msgid "Forgotten your password?" msgid "Forgotten your password?"
msgstr "Alterar minha senha" msgstr "Esqueceu sua senha?"
#: contrib/comments/templates/comments/form.html:8 #: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/object_history.html:3
@ -325,21 +326,21 @@ msgstr "Encerrar sessão"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#, fuzzy #, fuzzy
msgid "Ratings" msgid "Ratings"
msgstr "avaliação #1" msgstr "Avaliações"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Required" msgid "Required"
msgstr "" msgstr "Requerido"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Optional" msgid "Optional"
msgstr "" msgstr "Opcional"
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Post a photo" msgid "Post a photo"
msgstr "" msgstr "Postar uma foto"
#: contrib/comments/templates/comments/form.html:27 #: contrib/comments/templates/comments/form.html:27
#: contrib/comments/templates/comments/freeform.html:5 #: contrib/comments/templates/comments/freeform.html:5
@ -351,12 +352,12 @@ msgstr "Comentário"
#: contrib/comments/templates/comments/freeform.html:9 #: contrib/comments/templates/comments/freeform.html:9
#, fuzzy #, fuzzy
msgid "Preview comment" msgid "Preview comment"
msgstr "Comentário livre" msgstr "Pré visualizar comentário"
#: contrib/comments/templates/comments/freeform.html:4 #: contrib/comments/templates/comments/freeform.html:4
#, fuzzy #, fuzzy
msgid "Your name:" msgid "Your name:"
msgstr "usuário" msgstr "Seu nome:"
#: contrib/admin/filterspecs.py:40 #: contrib/admin/filterspecs.py:40
#, python-format #, python-format
@ -443,7 +444,7 @@ msgid ""
"sensitive." "sensitive."
msgstr "" msgstr ""
"Por favor entre usuário e senha corretos. Note que ambos os " "Por favor entre usuário e senha corretos. Note que ambos os "
"camposdiferenciam maiúsculas e minúsculas." "campos diferenciam maiúsculas e minúsculas."
#: contrib/admin/views/decorators.py:23 #: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25 #: contrib/admin/templates/admin/login.html:25
@ -468,7 +469,7 @@ msgstr ""
#: contrib/admin/views/decorators.py:82 #: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character." msgid "Usernames cannot contain the '@' character."
msgstr "Nomes de usuário não podem conter o caracter '@'." msgstr "Nomes de usuário não podem conter o caractere '@'."
#: contrib/admin/views/decorators.py:84 #: contrib/admin/views/decorators.py:84
#, python-format #, python-format
@ -553,7 +554,7 @@ msgstr "Um(a) ou mais %(fieldname)s em %(name)s:"
#: contrib/admin/views/main.py:508 #: contrib/admin/views/main.py:508
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "O(A) %(name)s \"%(obj)s\" foi adicionado com sucesso." msgstr "O(A) %(name)s \"%(obj)s\" foi excluído com sucesso."
#: contrib/admin/views/main.py:511 #: contrib/admin/views/main.py:511
msgid "Are you sure?" msgid "Are you sure?"
@ -746,7 +747,7 @@ msgid ""
"mail and should be fixed shortly. Thanks for your patience." "mail and should be fixed shortly. Thanks for your patience."
msgstr "" msgstr ""
"Houve um erro. Este foi reportado aos administradores do site através d e-" "Houve um erro. Este foi reportado aos administradores do site através d e-"
"mail e deve ser consertado em breve. Obrigado pela compreensão." "mail e deve ser corrigido em breve. Obrigado pela compreensão."
#: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8 #: contrib/admin/templates/admin/404.html:8
@ -760,7 +761,7 @@ msgstr "Desculpe, mas a página requisitada não pode ser encontrada."
#: contrib/admin/templates/admin/index.html:17 #: contrib/admin/templates/admin/index.html:17
#, python-format #, python-format
msgid "Models available in the %(name)s application." msgid "Models available in the %(name)s application."
msgstr "" msgstr "Modelos disponíveis na aplicação %(name)s"
#: contrib/admin/templates/admin/index.html:28 #: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15 #: contrib/admin/templates/admin/change_form.html:15
@ -794,7 +795,7 @@ msgstr "Adicionar %(name)s"
#: contrib/admin/templates/admin/login.html:22 #: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "Você <a href=\"/password_reset/\"esqueceu a senha</a>?" msgstr "Você <a href=\"/password_reset/\">esqueceu sua senha</a>?"
#: contrib/admin/templates/admin/base.html:23 #: contrib/admin/templates/admin/base.html:23
msgid "Welcome," msgid "Welcome,"
@ -836,7 +837,7 @@ msgstr "Por %(title)s "
#: contrib/admin/templates/admin/search_form.html:8 #: contrib/admin/templates/admin/search_form.html:8
msgid "Go" msgid "Go"
msgstr "" msgstr "Ir"
#: contrib/admin/templates/admin/change_form.html:21 #: contrib/admin/templates/admin/change_form.html:21
msgid "View on site" msgid "View on site"
@ -847,7 +848,7 @@ msgstr "Ver no site"
msgid "Please correct the error below." msgid "Please correct the error below."
msgid_plural "Please correct the errors below." msgid_plural "Please correct the errors below."
msgstr[0] "Por favor, corrija o erro abaixo." msgstr[0] "Por favor, corrija o erro abaixo."
msgstr[1] "Por favor, corrija o erro abaixo." msgstr[1] "Por favor, corrija os erros abaixo."
#: contrib/admin/templates/admin/change_form.html:48 #: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering" msgid "Ordering"
@ -930,8 +931,8 @@ msgid ""
"We've e-mailed a new password to the e-mail address you submitted. You " "We've e-mailed a new password to the e-mail address you submitted. You "
"should be receiving it shortly." "should be receiving it shortly."
msgstr "" msgstr ""
"Nós enviamos uma nova senha para o e-mail que você informou. Você deve estar " "Nós enviamos uma nova senha para o e-mail que você informou. Você deverá "
"recebendo uma mensagem em breve." "receber uma mensagem em breve."
#: contrib/admin/templates/registration/password_change_form.html:12 #: contrib/admin/templates/registration/password_change_form.html:12
msgid "" msgid ""
@ -973,7 +974,7 @@ msgstr "Sua nova senha é: %(new_password)s"
#: contrib/admin/templates/registration/password_reset_email.html:7 #: contrib/admin/templates/registration/password_reset_email.html:7
msgid "Feel free to change this password by going to this page:" msgid "Feel free to change this password by going to this page:"
msgstr "Sinta-se livre para alterar esta senha visitando esta página:" msgstr "Sinta-se a vontade para alterar esta senha visitando esta página:"
#: contrib/admin/templates/registration/password_reset_email.html:11 #: contrib/admin/templates/registration/password_reset_email.html:11
msgid "Your username, in case you've forgotten:" msgid "Your username, in case you've forgotten:"
@ -1040,17 +1041,17 @@ msgstr ""
#: contrib/admin/templates/admin_doc/bookmarklets.html:25 #: contrib/admin/templates/admin_doc/bookmarklets.html:25
msgid "Edit this object (current window)" msgid "Edit this object (current window)"
msgstr "Edita este objeto (janela atual)" msgstr "Editar este objeto (janela atual)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26 #: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object." msgid "Jumps to the admin page for pages that represent a single object."
msgstr "" msgstr ""
"Vai para a página de administração para páginas que representam um objeto " "Vai para a página de administração que representam um objeto "
"único." "único."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28 #: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)" msgid "Edit this object (new window)"
msgstr "Edita este objeto (nova janela)" msgstr "Editar este objeto (nova janela)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:29 #: contrib/admin/templates/admin_doc/bookmarklets.html:29
msgid "As above, but opens the admin page in a new window." msgid "As above, but opens the admin page in a new window."
@ -1135,7 +1136,7 @@ msgstr ""
#: contrib/flatpages/models.py:14 #: contrib/flatpages/models.py:14
msgid "registration required" msgid "registration required"
msgstr "é obrigatório registrar" msgstr "registro obrigatório"
#: contrib/flatpages/models.py:14 #: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page." msgid "If this is checked, only logged-in users will be able to view the page."
@ -1160,22 +1161,22 @@ msgstr "nome código"
#: contrib/auth/models.py:17 #: contrib/auth/models.py:17
#, fuzzy #, fuzzy
msgid "permission" msgid "permission"
msgstr "Permissão" msgstr "permissão"
#: contrib/auth/models.py:18 contrib/auth/models.py:27 #: contrib/auth/models.py:18 contrib/auth/models.py:27
#, fuzzy #, fuzzy
msgid "permissions" msgid "permissions"
msgstr "Permissões" msgstr "permissões"
#: contrib/auth/models.py:29 #: contrib/auth/models.py:29
#, fuzzy #, fuzzy
msgid "group" msgid "group"
msgstr "Grupo" msgstr "grupo"
#: contrib/auth/models.py:30 contrib/auth/models.py:65 #: contrib/auth/models.py:30 contrib/auth/models.py:65
#, fuzzy #, fuzzy
msgid "groups" msgid "groups"
msgstr "Grupos" msgstr "grupos"
#: contrib/auth/models.py:55 #: contrib/auth/models.py:55
msgid "username" msgid "username"
@ -1236,17 +1237,17 @@ msgstr ""
#: contrib/auth/models.py:67 #: contrib/auth/models.py:67
#, fuzzy #, fuzzy
msgid "user permissions" msgid "user permissions"
msgstr "Permissões" msgstr "permissões do usuário"
#: contrib/auth/models.py:70 #: contrib/auth/models.py:70
#, fuzzy #, fuzzy
msgid "user" msgid "user"
msgstr "Usuário" msgstr "usuário"
#: contrib/auth/models.py:71 #: contrib/auth/models.py:71
#, fuzzy #, fuzzy
msgid "users" msgid "users"
msgstr "Usuários" msgstr "usuários"
#: contrib/auth/models.py:76 #: contrib/auth/models.py:76
msgid "Personal info" msgid "Personal info"
@ -1267,7 +1268,7 @@ msgstr "Grupos"
#: contrib/auth/models.py:219 #: contrib/auth/models.py:219
#, fuzzy #, fuzzy
msgid "message" msgid "message"
msgstr "Mensagem" msgstr "mensagem"
#: contrib/auth/forms.py:30 #: contrib/auth/forms.py:30
msgid "" msgid ""
@ -1275,7 +1276,7 @@ msgid ""
"required for logging in." "required for logging in."
msgstr "" msgstr ""
"Seu navegador Web não parece estar com os cookies habilitados. Cookies são " "Seu navegador Web não parece estar com os cookies habilitados. Cookies são "
"requeridos para acesssar." "requeridos para acessar."
#: contrib/contenttypes/models.py:25 #: contrib/contenttypes/models.py:25
#, fuzzy #, fuzzy
@ -1417,52 +1418,52 @@ msgstr "Dezembro"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy #, fuzzy
msgid "jan" msgid "jan"
msgstr "e" msgstr "jan"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "feb" msgid "feb"
msgstr "" msgstr "fev"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "mar" msgid "mar"
msgstr "" msgstr "mar"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "apr" msgid "apr"
msgstr "" msgstr "abr"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy #, fuzzy
msgid "may" msgid "may"
msgstr "dia" msgstr "mai"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "jun" msgid "jun"
msgstr "" msgstr "jun"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "jul" msgid "jul"
msgstr "" msgstr "jul"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "aug" msgid "aug"
msgstr "" msgstr "ago"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "sep" msgid "sep"
msgstr "" msgstr "set"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "oct" msgid "oct"
msgstr "" msgstr "out"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "nov" msgid "nov"
msgstr "" msgstr "nov"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "dec" msgid "dec"
msgstr "" msgstr "dez"
#: utils/dates.py:27 #: utils/dates.py:27
msgid "Jan." msgid "Jan."
@ -1497,45 +1498,45 @@ msgstr "Dez."
msgid "year" msgid "year"
msgid_plural "years" msgid_plural "years"
msgstr[0] "ano" msgstr[0] "ano"
msgstr[1] "ano" msgstr[1] "anos"
#: utils/timesince.py:13 #: utils/timesince.py:13
#, fuzzy #, fuzzy
msgid "month" msgid "month"
msgid_plural "months" msgid_plural "months"
msgstr[0] "mês" msgstr[0] "mês"
msgstr[1] "mês" msgstr[1] "meses"
#: utils/timesince.py:14 #: utils/timesince.py:14
msgid "week" msgid "week"
msgid_plural "weeks" msgid_plural "weeks"
msgstr[0] "" msgstr[0] "semana"
msgstr[1] "" msgstr[1] "semanas"
#: utils/timesince.py:15 #: utils/timesince.py:15
#, fuzzy #, fuzzy
msgid "day" msgid "day"
msgid_plural "days" msgid_plural "days"
msgstr[0] "dia" msgstr[0] "dia"
msgstr[1] "dia" msgstr[1] "dias"
#: utils/timesince.py:16 #: utils/timesince.py:16
#, fuzzy #, fuzzy
msgid "hour" msgid "hour"
msgid_plural "hours" msgid_plural "hours"
msgstr[0] "hora" msgstr[0] "hora"
msgstr[1] "hora" msgstr[1] "horas"
#: utils/timesince.py:17 #: utils/timesince.py:17
#, fuzzy #, fuzzy
msgid "minute" msgid "minute"
msgid_plural "minutes" msgid_plural "minutes"
msgstr[0] "minuto" msgstr[0] "minuto"
msgstr[1] "minuto" msgstr[1] "minutos"
#: conf/global_settings.py:37 #: conf/global_settings.py:37
msgid "Bengali" msgid "Bengali"
msgstr "" msgstr "Bengalês"
#: conf/global_settings.py:38 #: conf/global_settings.py:38
msgid "Czech" msgid "Czech"
@ -1548,7 +1549,7 @@ msgstr ""
#: conf/global_settings.py:40 #: conf/global_settings.py:40
#, fuzzy #, fuzzy
msgid "Danish" msgid "Danish"
msgstr "Espanhol" msgstr "Dinamarquês"
#: conf/global_settings.py:41 #: conf/global_settings.py:41
msgid "German" msgid "German"
@ -1556,7 +1557,7 @@ msgstr "Alemão"
#: conf/global_settings.py:42 #: conf/global_settings.py:42
msgid "Greek" msgid "Greek"
msgstr "" msgstr "Grego"
#: conf/global_settings.py:43 #: conf/global_settings.py:43
msgid "English" msgid "English"
@ -1576,11 +1577,11 @@ msgstr "Galiciano"
#: conf/global_settings.py:47 #: conf/global_settings.py:47
msgid "Hungarian" msgid "Hungarian"
msgstr "" msgstr "Húngaro"
#: conf/global_settings.py:48 #: conf/global_settings.py:48
msgid "Hebrew" msgid "Hebrew"
msgstr "" msgstr "Hebraico"
#: conf/global_settings.py:49 #: conf/global_settings.py:49
msgid "Icelandic" msgid "Icelandic"
@ -1604,7 +1605,7 @@ msgstr "Norueguês"
#: conf/global_settings.py:54 #: conf/global_settings.py:54
msgid "Brazilian" msgid "Brazilian"
msgstr "Brazileiro" msgstr "Brasileiro"
#: conf/global_settings.py:55 #: conf/global_settings.py:55
msgid "Romanian" msgid "Romanian"
@ -1621,7 +1622,7 @@ msgstr "Eslovaco"
#: conf/global_settings.py:58 #: conf/global_settings.py:58
#, fuzzy #, fuzzy
msgid "Slovenian" msgid "Slovenian"
msgstr "Eslovaco" msgstr "Esloveno"
#: conf/global_settings.py:59 #: conf/global_settings.py:59
msgid "Serbian" msgid "Serbian"
@ -1634,7 +1635,7 @@ msgstr "Sueco"
#: conf/global_settings.py:61 #: conf/global_settings.py:61
#, fuzzy #, fuzzy
msgid "Ukrainian" msgid "Ukrainian"
msgstr "Brazileiro" msgstr "Ucraniano"
#: conf/global_settings.py:62 #: conf/global_settings.py:62
msgid "Simplified Chinese" msgid "Simplified Chinese"
@ -1689,7 +1690,7 @@ msgstr "Este valor não pode conter apenas dígitos."
#: core/validators.py:116 #: core/validators.py:116
msgid "Enter a whole number." msgid "Enter a whole number."
msgstr "Informe um número inteiro." msgstr "Informe um número completo."
#: core/validators.py:120 #: core/validators.py:120
msgid "Only alphabetical characters are allowed here." msgid "Only alphabetical characters are allowed here."
@ -1772,7 +1773,7 @@ msgstr "Informe uma abreviação válida de nome de um estado dos EUA."
msgid "Watch your mouth! The word %s is not allowed here." msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Lave sua boca! A palavra %s não é permitida aqui." msgstr[0] "Lave sua boca! A palavra %s não é permitida aqui."
msgstr[1] "Lave sua boca! A palavra %s não é permitida aqui." msgstr[1] "Lave sua boca! As palavras %s não são permitidas aqui."
#: core/validators.py:236 #: core/validators.py:236
#, python-format #, python-format
@ -1808,14 +1809,14 @@ msgstr "Este valor deve ser uma potência de %s."
#: core/validators.py:347 #: core/validators.py:347
msgid "Please enter a valid decimal number." msgid "Please enter a valid decimal number."
msgstr "Informe um número decimal." msgstr "Informe um número decimal válido."
#: core/validators.py:349 #: core/validators.py:349
#, fuzzy, python-format #, fuzzy, python-format
msgid "Please enter a valid decimal number with at most %s total digit." msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural "" msgid_plural ""
"Please enter a valid decimal number with at most %s total digits." "Please enter a valid decimal number with at most %s total digits."
msgstr[0] "Por favor entre com um número decimal com no máximo %s digitos." msgstr[0] "Por favor entre com um número decimal com no máximo %s digito."
msgstr[1] "Por favor entre com um número decimal com no máximo %s digitos." msgstr[1] "Por favor entre com um número decimal com no máximo %s digitos."
#: core/validators.py:352 #: core/validators.py:352
@ -1824,7 +1825,7 @@ msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural "" msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places." "Please enter a valid decimal number with at most %s decimal places."
msgstr[0] "Informe um número decimal com no máximo %s casa decimal." msgstr[0] "Informe um número decimal com no máximo %s casa decimal."
msgstr[1] "Informe um número decimal com no máximo %s casa decimal." msgstr[1] "Informe um número decimal com no máximo %s casas decimais."
#: core/validators.py:362 #: core/validators.py:362
#, python-format #, python-format
@ -1930,17 +1931,17 @@ msgstr "Este campo é requerido."
#: db/models/fields/__init__.py:337 #: db/models/fields/__init__.py:337
#, fuzzy #, fuzzy
msgid "This value must be an integer." msgid "This value must be an integer."
msgstr "Este valor deve ser uma potência de %s." msgstr "Este valor deve ser um inteiro."
#: db/models/fields/__init__.py:369 #: db/models/fields/__init__.py:369
#, fuzzy #, fuzzy
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Este valor deve ser uma potência de %s." msgstr "Este valor deve ser Verdadeiro ou Falso."
#: db/models/fields/__init__.py:385 #: db/models/fields/__init__.py:385
#, fuzzy #, fuzzy
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "Este campo é inválido." msgstr "Este campo não pode ser nulo."
#: db/models/fields/__init__.py:562 #: db/models/fields/__init__.py:562
msgid "Enter a valid filename." msgid "Enter a valid filename."
@ -1954,14 +1955,14 @@ msgstr "Por favor informe um %s válido."
#: db/models/fields/related.py:579 #: db/models/fields/related.py:579
#, fuzzy #, fuzzy
msgid "Separate multiple IDs with commas." msgid "Separate multiple IDs with commas."
msgstr " Separe IDs múltiplos com vírgulas." msgstr "Separe IDs múltiplos com vírgulas."
#: db/models/fields/related.py:581 #: db/models/fields/related.py:581
#, fuzzy #, fuzzy
msgid "" msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr "" msgstr ""
" Mantenha pressionado \"Control\", ou \"Command\" num Mac para selecionar " " Mantenha pressionado \"Control\", ou \"Command\" no Mac para selecionar "
"mais de uma opção." "mais de uma opção."
#: db/models/fields/related.py:625 #: db/models/fields/related.py:625
@ -1972,18 +1973,18 @@ msgid_plural ""
msgstr[0] "" msgstr[0] ""
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido." "Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido."
msgstr[1] "" msgstr[1] ""
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido." "Por favor, entre IDs válidos para %(self)s. Os valores %(value)r são inválidos."
#: forms/__init__.py:380 #: forms/__init__.py:380
#, fuzzy, python-format #, fuzzy, python-format
msgid "Ensure your text is less than %s character." msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters." msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Certifique-se de que seu texto tenha menos que %s caracteres." msgstr[0] "Certifique-se de que seu texto tenha menos que %s caractere."
msgstr[1] "Certifique-se de que seu texto tenha menos que %s caracteres." msgstr[1] "Certifique-se de que seu texto tenha menos que %s caracteres."
#: forms/__init__.py:385 #: forms/__init__.py:385
msgid "Line breaks are not allowed here." msgid "Line breaks are not allowed here."
msgstr "Não são permitidas múltiplas linhas aqui." msgstr "Não são permitidas quebras de linha aqui."
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 #: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
#, python-format #, python-format
@ -2037,7 +2038,7 @@ msgstr "sim,não,talvez"
#~ "\n" #~ "\n"
#~ "%(text)s" #~ "%(text)s"
#~ msgstr "" #~ msgstr ""
#~ "Este comentário foi envidao por um usuário que enviou menos de %(count)s " #~ "Este comentário foi enviado por um usuário que enviou menos de %(count)s "
#~ "comentário:\n" #~ "comentário:\n"
#~ "\n" #~ "\n"
#~ "%(text)sEste comentário foi enviado por um usuário que enviou menos de %" #~ "%(text)sEste comentário foi enviado por um usuário que enviou menos de %"
@ -2047,4 +2048,4 @@ msgstr "sim,não,talvez"
#, fuzzy #, fuzzy
#~ msgid "count" #~ msgid "count"
#~ msgstr "conteúdo" #~ msgstr "contagem"

View File

@ -1,15 +1,15 @@
# SOME DESCRIPTIVE TITLE. # Português do Brasil translation of django.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: django\n" "Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n" "POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2006-01-23 19:54-0200\n" "PO-Revision-Date: 2006-11-01 17:45-0300\n"
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n" "Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
"Language-Team: Português do Brasil <pt-br@li.org>\n" "Language-Team: Português do Brasil <pt-br@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -51,7 +51,7 @@ msgid ""
"January February March April May June July August September October November " "January February March April May June July August September October November "
"December" "December"
msgstr "" msgstr ""
"Janeiro Fevereiro Março Abrio Maio Junho Julho Agosto Setembro Outubro Novembro " "Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro "
"Dezembro" "Dezembro"
#: contrib/admin/media/js/dateparse.js:27 #: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,109 @@
# Django 0.95
# Copyright (C) 2006 Django
# This file is distributed under the same license as the Django package.
# Bahadır Kandemir <bahadir@pardus.org.tr>, 2006.
#
msgid ""
msgstr ""
"Project-Id-Version: Django 0.95\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-09-30 01:31+0300\n"
"PO-Revision-Date: 2006-09-30 01:31+0300\n"
"Last-Translator: Bahadır Kandemir <bahadir@pardus.org.tr>\n"
"Language-Team: Bahadır Kandemir <bahadir@pardus.org.tr>\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 "Mevcut %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Hepsini seç"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Ekle"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Kaldır"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Seçilen %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Seçiminizi yapın ve tıklayın "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Hepsini temizle"
#: 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 "Ocak Şubat Mart Nisan Mayıs Haziran Temmuz Ağustos Eylül Ekim Kasım "
"Aralık"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Pazar Pazartesi Salı Çarşamba Perşembe Cuma Cumartesi"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "P P S Ç P C C"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "Şimdi"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "Saat"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "Saat seçin"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "Geceyarısı"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "Sabah 6"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "Öğle"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "İptal"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "Bugün"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "Takvim"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "Dün"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Yarın"

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: django v1.0\n" "Project-Id-Version: django v1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:10+0200\n" "POT-Creation-Date: 2006-05-16 10:10+0200\n"
"PO-Revision-Date: 2006-05-17 13:47+0800\n" "PO-Revision-Date: 2006-09-01 22:05+0800\n"
"Last-Translator: limodou <limodou@gmail.com>\n" "Last-Translator: limodou <limodou@gmail.com>\n"
"Language-Team: Simplified Chinese <limodou@gmail.com>\n" "Language-Team: Simplified Chinese <limodou@gmail.com>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -1167,7 +1167,7 @@ msgstr "个人信息"
#: contrib/auth/models.py:77 #: contrib/auth/models.py:77
msgid "Permissions" msgid "Permissions"
msgstr "许可" msgstr "权限"
#: contrib/auth/models.py:78 #: contrib/auth/models.py:78
msgid "Important dates" msgid "Important dates"

View File

@ -3,22 +3,21 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
#, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: Django 0.95\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-03-21 18:43+0800\n" "POT-Creation-Date: 2006-03-21 18:43+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2006-09-25 08:35+0800\n"
"Last-Translator: FULL NAME <max@exoweb.net>\n" "Last-Translator: limodou <limodou@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: limodou <limodou@gmail.com>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33 #: contrib/admin/media/js/SelectFilter2.js:33
msgid "Available %s" msgid "Available %s"
msgstr "可 %s" msgstr "可 %s"
#: contrib/admin/media/js/SelectFilter2.js:41 #: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all" msgid "Choose all"
@ -30,34 +29,32 @@ msgstr "增加"
#: contrib/admin/media/js/SelectFilter2.js:48 #: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove" msgid "Remove"
msgstr "移出" msgstr "删除"
#: contrib/admin/media/js/SelectFilter2.js:53 #: contrib/admin/media/js/SelectFilter2.js:53
msgid "Chosen %s" msgid "Chosen %s"
msgstr "选 %s" msgstr "选中的 %s"
#: contrib/admin/media/js/SelectFilter2.js:54 #: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click " msgid "Select your choice(s) and click "
msgstr "挑选你的选择并点击 " msgstr "选择并点击 "
#: contrib/admin/media/js/SelectFilter2.js:59 #: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all" msgid "Clear all"
msgstr "清除所有" msgstr "清除全部"
#: contrib/admin/media/js/dateparse.js:32 #: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24 #: contrib/admin/media/js/calendar.js:24
msgid "" msgid "January February March April May June July August September October November December"
"January February March April May June July August September October November "
"December"
msgstr "一月 二月 三月 四月 五月 六月 六月 七月 八月 九月 十月 十一月 十二月" msgstr "一月 二月 三月 四月 五月 六月 六月 七月 八月 九月 十月 十一月 十二月"
#: contrib/admin/media/js/dateparse.js:33 #: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "星期 星期一 星期二 星期三 星期四 星期五 星期六" msgstr "星期 星期一 星期二 星期三 星期四 星期五 星期六"
#: contrib/admin/media/js/calendar.js:25 #: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S" msgid "S M T W T F S"
msgstr "日 月 火 水 木 金 土" msgstr "日 一 二 三 四 五 六"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
@ -105,3 +102,4 @@ msgstr "昨天"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow" msgid "Tomorrow"
msgstr "明天" msgstr "明天"

View File

@ -27,6 +27,10 @@ LANGUAGE_CODE = 'en-us'
SITE_ID = 1 SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# Absolute path to the directory that holds media. # Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/" # Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = '' MEDIA_ROOT = ''
@ -60,8 +64,9 @@ MIDDLEWARE_CLASSES = (
ROOT_URLCONF = '{{ project_name }}.urls' ROOT_URLCONF = '{{ project_name }}.urls'
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates". # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows. # Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
) )
INSTALLED_APPS = ( INSTALLED_APPS = (

View File

@ -1,4 +1,4 @@
body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; } body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
/* LINKS */ /* LINKS */
a:link, a:visited { color: #5b80b2; text-decoration:none; } a:link, a:visited { color: #5b80b2; text-decoration:none; }

View File

@ -171,7 +171,6 @@ var DateTimeShortcuts = {
cal_nav_prev.className = 'calendarnav-previous'; cal_nav_prev.className = 'calendarnav-previous';
var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');'); var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
cal_nav_next.className = 'calendarnav-next'; cal_nav_next.className = 'calendarnav-next';
cal_box.appendChild(cal_nav);
// main box // main box
var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num); var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);

View File

@ -0,0 +1,28 @@
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block after_field_sets %}
<p>{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}</p>
<fieldset class="module aligned">
<div class="form-row">
{{ form.username.html_error_list }}
<label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
<p class="help">{{ username_help_text }}</p>
</div>
<div class="form-row">
{{ form.password1.html_error_list }}
<label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
</div>
<div class="form-row">
{{ form.password2.html_error_list }}
<label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
<p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
</div>
</fieldset>
{% endblock %}

View File

@ -6,6 +6,7 @@
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %} {% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %}
{% block extrastyle %}{% endblock %} {% block extrastyle %}{% endblock %}
{% block extrahead %}{% endblock %} {% block extrahead %}{% endblock %}
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
</head> </head>
{% load i18n %} {% load i18n %}

View File

@ -21,7 +21,7 @@
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%} {% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
</ul> </ul>
{% endif %}{% endif %} {% endif %}{% endif %}
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post">{% block form_top %}{% endblock %} <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
<div> <div>
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %} {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
{% if opts.admin.save_on_top %}{% submit_row %}{% endif %} {% if opts.admin.save_on_top %}{% submit_row %}{% endif %}

View File

@ -7,6 +7,7 @@
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th> <th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</tr></thead>
{% for fcw in bound_related_object.form_field_collection_wrappers %} {% for fcw in bound_related_object.form_field_collection_wrappers %}
{% if change %}{% if original_row_needed %} {% if change %}{% if original_row_needed %}
{% if fcw.obj.original %} {% if fcw.obj.original %}

View File

@ -19,7 +19,7 @@
<div class="form-row"> <div class="form-row">
<label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" /> <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
<input type="hidden" name="this_is_the_login_form" value="1" /> <input type="hidden" name="this_is_the_login_form" value="1" />
<input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %} <input type="hidden" name="post_data" value="{{ post_data }}" /> {#<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>#}
</div> </div>
<div class="submit-row"> <div class="submit-row">
<label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" /> <label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" />

View File

@ -35,7 +35,7 @@
<tr> <tr>
<td>{{ field.name }}</td> <td>{{ field.name }}</td>
<td>{{ field.data_type }}</td> <td>{{ field.data_type }}</td>
<td>{% if field.verbose %}{{ field.verbose|escape }}{% endif %}{% if field.help_text %} - {{ field.help_text|escape }}{% endif %}</td> <td>{% if field.verbose %}{{ field.verbose }}{% endif %}{% if field.help_text %} - {{ field.help_text }}{% endif %}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -8,7 +8,7 @@
<h1>{{ name }}</h1> <h1>{{ name }}</h1>
<h2 class="subhead">{{ summary|escape }}</h2> <h2 class="subhead">{{ summary }}</h2>
<p>{{ body }}</p> <p>{{ body }}</p>

View File

@ -160,8 +160,10 @@ class EditInlineNode(template.Node):
context.push() context.push()
if relation.field.rel.edit_inline == models.TABULAR: if relation.field.rel.edit_inline == models.TABULAR:
bound_related_object_class = TabularBoundRelatedObject bound_related_object_class = TabularBoundRelatedObject
else: elif relation.field.rel.edit_inline == models.STACKED:
bound_related_object_class = StackedBoundRelatedObject bound_related_object_class = StackedBoundRelatedObject
else:
bound_related_object_class = relation.field.rel.edit_inline
original = context.get('original', None) original = context.get('original', None)
bound_related_object = relation.bind(context['form'], original, bound_related_object_class) bound_related_object = relation.bind(context['form'], original, bound_related_object_class)
context['bound_related_object'] = bound_related_object context['bound_related_object'] = bound_related_object
@ -196,7 +198,7 @@ def filter_interface_script_maybe(bound_field):
if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface: 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 '<script type="text/javascript">addEvent(window, "load", function(e) {' \
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % ( ' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
f.name, f.verbose_name, f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX) f.name, f.verbose_name.replace('"', '\\"'), f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
else: else:
return '' return ''
filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe) filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe)

View File

@ -21,13 +21,15 @@ urlpatterns = patterns('',
('^doc/tags/$', 'django.contrib.admin.views.doc.template_tag_index'), ('^doc/tags/$', 'django.contrib.admin.views.doc.template_tag_index'),
('^doc/filters/$', 'django.contrib.admin.views.doc.template_filter_index'), ('^doc/filters/$', 'django.contrib.admin.views.doc.template_filter_index'),
('^doc/views/$', 'django.contrib.admin.views.doc.view_index'), ('^doc/views/$', 'django.contrib.admin.views.doc.view_index'),
('^doc/views/jump/$', 'django.contrib.admin.views.doc.jump_to_view'),
('^doc/views/(?P<view>[^/]+)/$', 'django.contrib.admin.views.doc.view_detail'), ('^doc/views/(?P<view>[^/]+)/$', 'django.contrib.admin.views.doc.view_detail'),
('^doc/models/$', 'django.contrib.admin.views.doc.model_index'), ('^doc/models/$', 'django.contrib.admin.views.doc.model_index'),
('^doc/models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$', 'django.contrib.admin.views.doc.model_detail'), ('^doc/models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$', 'django.contrib.admin.views.doc.model_detail'),
# ('^doc/templates/$', 'django.views.admin.doc.template_index'), # ('^doc/templates/$', 'django.views.admin.doc.template_index'),
('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'), ('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'),
# "Add user" -- a special-case view
('^auth/user/add/$', 'django.contrib.admin.views.auth.user_add_stage'),
# Add/change/delete/history # Add/change/delete/history
('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'), ('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'), ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),

View File

@ -0,0 +1,44 @@
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django import forms, template
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
def user_add_stage(request):
if not request.user.has_perm('auth.change_user'):
raise PermissionDenied
manipulator = UserCreationForm()
if request.method == 'POST':
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
if not errors:
new_user = manipulator.save(new_data)
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user}
if request.POST.has_key("_addanother"):
request.user.message_set.create(message=msg)
return HttpResponseRedirect(request.path)
else:
request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
return HttpResponseRedirect('../%s/' % new_user.id)
else:
errors = new_data = {}
form = forms.FormWrapper(manipulator, new_data, errors)
return render_to_response('admin/auth/user/add_form.html', {
'title': _('Add user'),
'form': form,
'is_popup': request.REQUEST.has_key('_popup'),
'add': True,
'change': False,
'has_delete_permission': False,
'has_change_permission': True,
'has_file_field': False,
'has_absolute_url': False,
'auto_populated_fields': (),
'bound_field_sets': (),
'first_form_field_id': 'id_username',
'opts': User._meta,
'username_help_text': User._meta.get_field('username').help_text,
}, context_instance=template.RequestContext(request))
user_add_stage = staff_member_required(user_add_stage)

View File

@ -87,7 +87,7 @@ def staff_member_required(view_func):
# The user data is correct; log in the user in and continue. # The user data is correct; log in the user in and continue.
else: else:
if user.is_staff: if user.is_active and user.is_staff:
login(request, user) login(request, user)
# TODO: set last_login with an event. # TODO: set last_login with an event.
user.last_login = datetime.datetime.now() user.last_login = datetime.datetime.now()

View File

@ -43,11 +43,11 @@ def template_tag_index(request):
for tag_name, tag_func in library.tags.items(): for tag_name, tag_func in library.tags.items():
title, body, metadata = utils.parse_docstring(tag_func.__doc__) title, body, metadata = utils.parse_docstring(tag_func.__doc__)
if title: if title:
title = utils.parse_rst(title, 'tag', 'tag:' + tag_name) title = utils.parse_rst(title, 'tag', _('tag:') + tag_name)
if body: if body:
body = utils.parse_rst(body, 'tag', 'tag:' + tag_name) body = utils.parse_rst(body, 'tag', _('tag:') + tag_name)
for key in metadata: for key in metadata:
metadata[key] = utils.parse_rst(metadata[key], 'tag', 'tag:' + tag_name) metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name)
if library in template.builtins: if library in template.builtins:
tag_library = None tag_library = None
else: else:
@ -74,11 +74,11 @@ def template_filter_index(request):
for filter_name, filter_func in library.filters.items(): for filter_name, filter_func in library.filters.items():
title, body, metadata = utils.parse_docstring(filter_func.__doc__) title, body, metadata = utils.parse_docstring(filter_func.__doc__)
if title: if title:
title = utils.parse_rst(title, 'filter', 'filter:' + filter_name) title = utils.parse_rst(title, 'filter', _('filter:') + filter_name)
if body: if body:
body = utils.parse_rst(body, 'filter', 'filter:' + filter_name) body = utils.parse_rst(body, 'filter', _('filter:') + filter_name)
for key in metadata: for key in metadata:
metadata[key] = utils.parse_rst(metadata[key], 'filter', 'filter:' + filter_name) metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name)
if library in template.builtins: if library in template.builtins:
tag_library = None tag_library = None
else: else:
@ -98,13 +98,13 @@ def view_index(request):
return missing_docutils_page(request) return missing_docutils_page(request)
if settings.ADMIN_FOR: if settings.ADMIN_FOR:
settings_modules = [__import__(m, '', '', ['']) for m in settings.ADMIN_FOR] settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR]
else: else:
settings_modules = [settings] settings_modules = [settings]
views = [] views = []
for settings_mod in settings_modules: for settings_mod in settings_modules:
urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', ['']) urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, [''])
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
if Site._meta.installed: if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID) site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
@ -127,16 +127,16 @@ def view_detail(request, view):
mod, func = urlresolvers.get_mod_func(view) mod, func = urlresolvers.get_mod_func(view)
try: try:
view_func = getattr(__import__(mod, '', '', ['']), func) view_func = getattr(__import__(mod, {}, {}, ['']), func)
except (ImportError, AttributeError): except (ImportError, AttributeError):
raise Http404 raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__) title, body, metadata = utils.parse_docstring(view_func.__doc__)
if title: if title:
title = utils.parse_rst(title, 'view', 'view:' + view) title = utils.parse_rst(title, 'view', _('view:') + view)
if body: if body:
body = utils.parse_rst(body, 'view', 'view:' + view) body = utils.parse_rst(body, 'view', _('view:') + view)
for key in metadata: for key in metadata:
metadata[key] = utils.parse_rst(metadata[key], 'model', 'view:' + view) metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view)
return render_to_response('admin_doc/view_detail.html', { return render_to_response('admin_doc/view_detail.html', {
'name': view, 'name': view,
'summary': title, 'summary': title,
@ -161,14 +161,14 @@ def model_detail(request, app_label, model_name):
try: try:
app_mod = models.get_app(app_label) app_mod = models.get_app(app_label)
except ImproperlyConfigured: except ImproperlyConfigured:
raise Http404, "App %r not found" % app_label raise Http404, _("App %r not found") % app_label
model = None model = None
for m in models.get_models(app_mod): for m in models.get_models(app_mod):
if m._meta.object_name.lower() == model_name: if m._meta.object_name.lower() == model_name:
model = m model = m
break break
if model is None: if model is None:
raise Http404, "Model %r not found in app %r" % (model_name, app_label) raise Http404, _("Model %r not found in app %r") % (model_name, app_label)
opts = model._meta opts = model._meta
@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name):
if isinstance(field, models.ForeignKey): if isinstance(field, models.ForeignKey):
data_type = related_object_name = field.rel.to.__name__ data_type = related_object_name = field.rel.to.__name__
app_label = field.rel.to._meta.app_label app_label = field.rel.to._meta.app_label
verbose = utils.parse_rst(("the related `%s.%s` object" % (app_label, data_type)), 'model', 'model:' + data_type) verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type)
else: else:
data_type = get_readable_field_data_type(field) data_type = get_readable_field_data_type(field)
verbose = field.verbose_name verbose = field.verbose_name
@ -202,7 +202,7 @@ def model_detail(request, app_label, model_name):
continue continue
verbose = func.__doc__ verbose = func.__doc__
if verbose: if verbose:
verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', 'model:' + opts.module_name) verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.module_name)
fields.append({ fields.append({
'name': func_name, 'name': func_name,
'data_type': get_return_data_type(func_name), 'data_type': get_return_data_type(func_name),
@ -211,22 +211,22 @@ def model_detail(request, app_label, model_name):
# Gather related objects # Gather related objects
for rel in opts.get_all_related_objects(): for rel in opts.get_all_related_objects():
verbose = "related `%s.%s` objects" % (rel.opts.app_label, rel.opts.object_name) verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name)
accessor = rel.get_accessor_name() accessor = rel.get_accessor_name()
fields.append({ fields.append({
'name' : "%s.all" % accessor, 'name' : "%s.all" % accessor,
'data_type' : 'List', 'data_type' : 'List',
'verbose' : utils.parse_rst("all " + verbose , 'model', 'model:' + opts.module_name), 'verbose' : utils.parse_rst(_("all %s") % verbose , 'model', _('model:') + opts.module_name),
}) })
fields.append({ fields.append({
'name' : "%s.count" % accessor, 'name' : "%s.count" % accessor,
'data_type' : 'Integer', 'data_type' : 'Integer',
'verbose' : utils.parse_rst("number of " + verbose , 'model', 'model:' + opts.module_name), 'verbose' : utils.parse_rst(_("number of %s") % verbose , 'model', _('model:') + opts.module_name),
}) })
return render_to_response('admin_doc/model_detail.html', { return render_to_response('admin_doc/model_detail.html', {
'name': '%s.%s' % (opts.app_label, opts.object_name), 'name': '%s.%s' % (opts.app_label, opts.object_name),
'summary': "Fields on %s objects" % opts.object_name, 'summary': _("Fields on %s objects") % opts.object_name,
'description': model.__doc__, 'description': model.__doc__,
'fields': fields, 'fields': fields,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
@ -235,7 +235,7 @@ model_detail = staff_member_required(model_detail)
def template_detail(request, template): def template_detail(request, template):
templates = [] templates = []
for site_settings_module in settings.ADMIN_FOR: for site_settings_module in settings.ADMIN_FOR:
settings_mod = __import__(site_settings_module, '', '', ['']) settings_mod = __import__(site_settings_module, {}, {}, [''])
if Site._meta.installed: if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID) site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
else: else:
@ -328,15 +328,19 @@ def extract_views_from_urlpatterns(urlpatterns, base=''):
""" """
views = [] views = []
for p in urlpatterns: for p in urlpatterns:
if hasattr(p, 'get_callback'): if hasattr(p, '_get_callback'):
try: try:
views.append((p.get_callback(), base + p.regex.pattern)) views.append((p._get_callback(), base + p.regex.pattern))
except ViewDoesNotExist: except ViewDoesNotExist:
continue continue
elif hasattr(p, '_get_url_patterns'): elif hasattr(p, '_get_url_patterns'):
views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern)) try:
patterns = p.url_patterns
except ImportError:
continue
views.extend(extract_views_from_urlpatterns(patterns, base + p.regex.pattern))
else: else:
raise TypeError, "%s does not appear to be a urlpattern object" % p raise TypeError, _("%s does not appear to be a urlpattern object") % p
return views return views
named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)') named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)')

View File

@ -268,6 +268,8 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
post_url_continue += "?_popup=1" post_url_continue += "?_popup=1"
return HttpResponseRedirect(post_url_continue % pk_value) return HttpResponseRedirect(post_url_continue % pk_value)
if request.POST.has_key("_popup"): if request.POST.has_key("_popup"):
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>' % \ return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
(pk_value, str(new_object).replace('"', '\\"'))) (pk_value, str(new_object).replace('"', '\\"')))
elif request.POST.has_key("_addanother"): elif request.POST.has_key("_addanother"):
@ -455,7 +457,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
# permission to delete them, add the missing perm to perms_needed. # permission to delete them, add the missing perm to perms_needed.
if related.opts.admin and has_related_objs: if related.opts.admin and has_related_objs:
if not has_permission(user, related.opts.get_delete_permission(), related): if not has_permission(user, related.opts.get_delete_permission(), related):
perms_needed.add(rel_opts_name) perms_needed.add(related.opts.verbose_name)
for related in opts.get_all_related_many_to_many_objects(): for related in opts.get_all_related_many_to_many_objects():
if related.opts in opts_seen: if related.opts in opts_seen:
continue continue
@ -713,10 +715,22 @@ class ChangeList(object):
qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field) qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field)
# Apply keyword searches. # Apply keyword searches.
def construct_search(field_name):
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name
if self.lookup_opts.admin.search_fields and self.query: if self.lookup_opts.admin.search_fields and self.query:
for bit in self.query.split(): for bit in self.query.split():
or_queries = [models.Q(**{'%s__icontains' % field_name: bit}) for field_name in self.lookup_opts.admin.search_fields] or_queries = [models.Q(**{construct_search(field_name): bit}) for field_name in self.lookup_opts.admin.search_fields]
other_qs = QuerySet(self.model) other_qs = QuerySet(self.model)
if qs._select_related:
other_qs = other_qs.select_related()
other_qs = other_qs.filter(reduce(operator.or_, or_queries)) other_qs = other_qs.filter(reduce(operator.or_, or_queries))
qs = qs & other_qs qs = qs & other_qs

View File

@ -14,7 +14,7 @@ def template_validator(request):
# get a dict of {site_id : settings_module} for the validator # get a dict of {site_id : settings_module} for the validator
settings_modules = {} settings_modules = {}
for mod in settings.ADMIN_FOR: for mod in settings.ADMIN_FOR:
settings_module = __import__(mod, '', '', ['']) settings_module = __import__(mod, {}, {}, [''])
settings_modules[settings_module.SITE_ID] = settings_module settings_modules[settings_module.SITE_ID] = settings_module
manipulator = TemplateValidator(settings_modules) manipulator = TemplateValidator(settings_modules)
new_data, errors = {}, {} new_data, errors = {}, {}

View File

@ -38,7 +38,7 @@ def load_backend(path):
i = path.rfind('.') i = path.rfind('.')
module, attr = path[:i], path[i+1:] module, attr = path[:i], path[i+1:]
try: try:
mod = __import__(module, '', '', [attr]) mod = __import__(module, {}, {}, [attr])
except ImportError, e: except ImportError, e:
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e) raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
try: try:

View File

@ -46,6 +46,7 @@ def createsuperuser(username=None, email=None, password=None):
if not username.isalnum(): if not username.isalnum():
sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n") sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n")
username = None username = None
continue
try: try:
User.objects.get(username=username) User.objects.get(username=username)
except User.DoesNotExist: except User.DoesNotExist:

View File

@ -26,3 +26,11 @@ login_required.__doc__ = (
to the log-in page if necessary. to the log-in page if necessary.
""" """
) )
def permission_required(perm, login_url=LOGIN_URL):
"""
Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary.
"""
return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)

View File

@ -5,6 +5,28 @@ from django.template import Context, loader
from django.core import validators from django.core import validators
from django import forms from django import forms
class UserCreationForm(forms.Manipulator):
"A form that creates a user, with no privileges, from the given username and password."
def __init__(self):
self.fields = (
forms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
forms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
forms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
)
def isValidUsername(self, field_data, all_data):
try:
User.objects.get(username=field_data)
except User.DoesNotExist:
return
raise validators.ValidationError, _('A user with that username already exists.')
def save(self, new_data):
"Creates the user."
return User.objects.create_user(new_data['username'], '', new_data['password1'])
class AuthenticationForm(forms.Manipulator): class AuthenticationForm(forms.Manipulator):
""" """
Base class for authenticating users. Extend this to get a form that accepts Base class for authenticating users. Extend this to get a form that accepts
@ -59,7 +81,7 @@ class PasswordResetForm(forms.Manipulator):
try: try:
self.user_cache = User.objects.get(email__iexact=new_data) self.user_cache = User.objects.get(email__iexact=new_data)
except User.DoesNotExist: except User.DoesNotExist:
raise validators.ValidationError, "That e-mail address doesn't have an associated user acount. Are you sure you've registered?" raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'): def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
"Calculates a new password randomly and sends it to the user" "Calculates a new password randomly and sends it to the user"
@ -91,14 +113,14 @@ class PasswordChangeForm(forms.Manipulator):
forms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True, forms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True,
validator_list=[self.isValidOldPassword]), validator_list=[self.isValidOldPassword]),
forms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True, forms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True,
validator_list=[validators.AlwaysMatchesOtherField('new_password2', "The two 'new password' fields didn't match.")]), validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
forms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True), forms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True),
) )
def isValidOldPassword(self, new_data, all_data): def isValidOldPassword(self, new_data, all_data):
"Validates that the old_password field is correct." "Validates that the old_password field is correct."
if not self.user.check_password(new_data): if not self.user.check_password(new_data):
raise validators.ValidationError, "Your old password was entered incorrectly. Please enter it again." raise validators.ValidationError, _("Your old password was entered incorrectly. Please enter it again.")
def save(self, new_data): def save(self, new_data):
"Saves the new password." "Saves the new password."

View File

@ -22,6 +22,8 @@ def authenhandler(req, **kwargs):
os.environ['DJANGO_SETTINGS_MODULE'] = settings_module os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django import db
db.reset_queries()
# check that the username is valid # check that the username is valid
kwargs = {'username': req.user, 'is_active': True} kwargs = {'username': req.user, 'is_active': True}
@ -29,6 +31,7 @@ def authenhandler(req, **kwargs):
kwargs['is_staff'] = True kwargs['is_staff'] = True
if superuser_only: if superuser_only:
kwargs['is_superuser'] = True kwargs['is_superuser'] = True
try:
try: try:
user = User.objects.get(**kwargs) user = User.objects.get(**kwargs)
except User.DoesNotExist: except User.DoesNotExist:
@ -45,3 +48,5 @@ def authenhandler(req, **kwargs):
return apache.OK return apache.OK
else: else:
return apache.HTTP_UNAUTHORIZED return apache.HTTP_UNAUTHORIZED
finally:
db.connection.close()

View File

@ -16,7 +16,7 @@ def _get_all_permissions(opts):
perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name))) perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name)))
return perms + list(opts.permissions) return perms + list(opts.permissions)
def create_permissions(app, created_models): def create_permissions(app, created_models, verbosity):
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
app_models = get_models(app) app_models = get_models(app)
@ -27,13 +27,13 @@ def create_permissions(app, created_models):
for codename, name in _get_all_permissions(klass._meta): for codename, name in _get_all_permissions(klass._meta):
p, created = Permission.objects.get_or_create(codename=codename, content_type__pk=ctype.id, p, created = Permission.objects.get_or_create(codename=codename, content_type__pk=ctype.id,
defaults={'name': name, 'content_type': ctype}) defaults={'name': name, 'content_type': ctype})
if created: if created and verbosity >= 2:
print "Adding permission '%s'" % p print "Adding permission '%s'" % p
def create_superuser(app, created_models): def create_superuser(app, created_models, verbosity, **kwargs):
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.create_superuser import createsuperuser as do_create from django.contrib.auth.create_superuser import createsuperuser as do_create
if User in created_models: if User in created_models and kwargs.get('interactive', True):
msg = "\nYou just installed Django's auth system, which means you don't have " \ msg = "\nYou just installed Django's auth system, which means you don't have " \
"any superusers defined.\nWould you like to create one now? (yes/no): " "any superusers defined.\nWould you like to create one now? (yes/no): "
confirm = raw_input(msg) confirm = raw_input(msg)

View File

@ -1,12 +1,9 @@
class LazyUser(object): class LazyUser(object):
def __init__(self):
self._user = None
def __get__(self, request, obj_type=None): def __get__(self, request, obj_type=None):
if self._user is None: if not hasattr(request, '_cached_user'):
from django.contrib.auth import get_user from django.contrib.auth import get_user
self._user = get_user(request) request._cached_user = get_user(request)
return self._user return request._cached_user
class AuthenticationMiddleware(object): class AuthenticationMiddleware(object):
def process_request(self, request): def process_request(self, request):

View File

@ -33,7 +33,7 @@ class Permission(models.Model):
Permissions are set globally per type of object, not per specific object instance. It is possible to say "Mary may change news stories," but it's not currently possible to say "Mary may change news stories, but only the ones she created herself" or "Mary may only change news stories that have a certain status or publication date." Permissions are set globally per type of object, not per specific object instance. It is possible to say "Mary may change news stories," but it's not currently possible to say "Mary may change news stories, but only the ones she created herself" or "Mary may only change news stories that have a certain status or publication date."
Three basic permissions -- add, create and delete -- are automatically created for each Django 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'), maxlength=50)
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
@ -92,9 +92,9 @@ class User(models.Model):
last_name = models.CharField(_('last name'), maxlength=30, blank=True) last_name = models.CharField(_('last name'), maxlength=30, blank=True)
email = models.EmailField(_('e-mail address'), blank=True) email = models.EmailField(_('e-mail address'), blank=True)
password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]'")) password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]'"))
is_staff = models.BooleanField(_('staff status'), help_text=_("Designates whether the user can log into this admin site.")) 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_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'), help_text=_("Designates that this user has all permissions without explicitly assigning them.")) is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
last_login = models.DateTimeField(_('last login'), default=models.LazyDate()) last_login = models.DateTimeField(_('last login'), default=models.LazyDate())
date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate()) date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate())
groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True, groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
@ -216,6 +216,8 @@ class User(models.Model):
def has_module_perms(self, app_label): def has_module_perms(self, app_label):
"Returns True if the user has any permissions in the given app label." "Returns True if the user has any permissions in the given app label."
if not self.is_active:
return False
if self.is_superuser: if self.is_superuser:
return True return True
return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label])) return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]))
@ -268,6 +270,15 @@ class AnonymousUser(object):
def __str__(self): def __str__(self):
return 'AnonymousUser' return 'AnonymousUser'
def __eq__(self, other):
return isinstance(other, self.__class__)
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return 1 # instances always return the same hash value
def save(self): def save(self):
raise NotImplementedError raise NotImplementedError

View File

@ -109,7 +109,7 @@ class PublicCommentManipulator(AuthenticationForm):
# send the comment to the managers. # send the comment to the managers.
if self.user_cache.comment_set.count() <= settings.COMMENTS_FIRST_FEW: 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 = ngettext('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') % \ '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()} {'count': settings.COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
mail_managers("Comment posted by rookie user", message) 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.get_group_list()]:
@ -217,7 +217,7 @@ def post_comment(request):
errors = manipulator.get_validation_errors(new_data) errors = manipulator.get_validation_errors(new_data)
# If user gave correct username/password and wasn't already logged in, log them in # If user gave correct username/password and wasn't already logged in, log them in
# so they don't have to enter a username/password again. # so they don't have to enter a username/password again.
if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']): if manipulator.get_user() and not manipulator.get_user().is_authenticated() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
from django.contrib.auth import login from django.contrib.auth import login
login(request, manipulator.get_user()) login(request, manipulator.get_user())
if errors or request.POST.has_key('preview'): if errors or request.POST.has_key('preview'):

View File

@ -5,7 +5,7 @@ Creates content types for all installed models.
from django.dispatch import dispatcher from django.dispatch import dispatcher
from django.db.models import get_models, signals from django.db.models import get_models, signals
def create_contenttypes(app, created_models): def create_contenttypes(app, created_models, verbosity):
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
app_models = get_models(app) app_models = get_models(app)
if not app_models: if not app_models:
@ -19,6 +19,7 @@ def create_contenttypes(app, created_models):
ct = ContentType(name=str(opts.verbose_name), ct = ContentType(name=str(opts.verbose_name),
app_label=opts.app_label, model=opts.object_name.lower()) app_label=opts.app_label, model=opts.object_name.lower())
ct.save() ct.save()
if verbosity >= 2:
print "Adding content type '%s | %s'" % (ct.app_label, ct.model) print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
dispatcher.connect(create_contenttypes, signal=signals.post_syncdb) dispatcher.connect(create_contenttypes, signal=signals.post_syncdb)

View File

@ -2,7 +2,7 @@ This is an optional add-on app, flatpages.
For full documentation, see either of these: For full documentation, see either of these:
* The file django/docs/flatpages.txt in the Django distribution * The file docs/flatpages.txt in the Django distribution
* http://www.djangoproject.com/documentation/flatpages/ on the Web * http://www.djangoproject.com/documentation/flatpages/ on the Web
Both have identical content. Both have identical content.

View File

@ -3,6 +3,7 @@ from django.template import loader, RequestContext
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.http import HttpResponse from django.http import HttpResponse
from django.conf import settings from django.conf import settings
from django.core.xheaders import populate_xheaders
DEFAULT_TEMPLATE = 'flatpages/default.html' DEFAULT_TEMPLATE = 'flatpages/default.html'
@ -32,4 +33,6 @@ def flatpage(request, url):
c = RequestContext(request, { c = RequestContext(request, {
'flatpage': f, 'flatpage': f,
}) })
return HttpResponse(t.render(c)) response = HttpResponse(t.render(c))
populate_xheaders(request, response, FlatPage, f.id)
return response

View File

@ -88,5 +88,6 @@ class SessionMiddleware(object):
new_session = Session.objects.save(session_key, request.session._session, new_session = Session.objects.save(session_key, request.session._session,
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key, response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN) max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
secure=settings.SESSION_COOKIE_SECURE or None)
return response return response

View File

@ -0,0 +1,90 @@
from django.core import urlresolvers
import urllib
PING_URL = "http://www.google.com/webmasters/sitemaps/ping"
class SitemapNotFound(Exception):
pass
def ping_google(sitemap_url=None, ping_url=PING_URL):
"""
Alerts Google that the sitemap for the current site has been updated.
If sitemap_url is provided, it should be an absolute path to the sitemap
for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this
function will attempt to deduce it by using urlresolvers.reverse().
"""
if sitemap_url is None:
try:
# First, try to get the "index" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.index')
except urlresolvers.NoReverseMatch:
try:
# Next, try for the "global" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap')
except urlresolvers.NoReverseMatch:
pass
if sitemap_url is None:
raise SitemapNotFound("You didn't provide a sitemap_url, and the sitemap URL couldn't be auto-detected.")
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
url = "%s%s" % (current_site.domain, sitemap)
params = urllib.urlencode({'sitemap':url})
urllib.urlopen("%s?%s" % (ping_url, params))
class Sitemap:
def __get(self, name, obj, default=None):
try:
attr = getattr(self, name)
except AttributeError:
return default
if callable(attr):
return attr(obj)
return attr
def items(self):
return []
def location(self, obj):
return obj.get_absolute_url()
def get_urls(self):
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
urls = []
for item in self.items():
loc = "http://%s%s" % (current_site.domain, self.__get('location', item))
url_info = {
'location': loc,
'lastmod': self.__get('lastmod', item, None),
'changefreq': self.__get('changefreq', item, None),
'priority': self.__get('priority', item, None)
}
urls.append(url_info)
return urls
class FlatPageSitemap(Sitemap):
def items(self):
from django.contrib.sites.models import Site
current_site = Site.objects.get_current()
return current_site.flatpage_set.all()
class GenericSitemap(Sitemap):
priority = None
changefreq = None
def __init__(self, info_dict, priority=None, changefreq=None):
self.queryset = info_dict['queryset']
self.date_field = info_dict.get('date_field', None)
self.priority = priority
self.changefreq = changefreq
def items(self):
# Make sure to return a clone; we don't want premature evaluation.
return self.queryset.filter()
def lastmod(self, item):
if self.date_field is not None:
return getattr(item, self.date_field)
return None

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
{% spaceless %}
{% for url in urlset %}
<url>
<loc>{{ url.location|escape }}</loc>
{% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
{% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
{% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
</url>
{% endfor %}
{% endspaceless %}
</urlset>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">
{% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %}
</sitemapindex>

View File

@ -0,0 +1,30 @@
from django.http import HttpResponse, Http404
from django.template import loader
from django.contrib.sites.models import Site
from django.core import urlresolvers
def index(request, sitemaps):
current_site = Site.objects.get_current()
sites = []
protocol = request.is_secure() and 'https' or 'http'
for section in sitemaps.keys():
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap', kwargs={'section': section})
sites.append('%s://%s%s' % (protocol, current_site.domain, sitemap_url))
xml = loader.render_to_string('sitemap_index.xml', {'sitemaps': sites})
return HttpResponse(xml, mimetype='application/xml')
def sitemap(request, sitemaps, section=None):
maps, urls = [], []
if section is not None:
if not sitemaps.has_key(section):
raise Http404("No sitemap available for section: %r" % section)
maps.append(sitemaps[section])
else:
maps = sitemaps.values()
for site in maps:
if callable(site):
urls.extend(site().get_urls())
else:
urls.extend(site.get_urls())
xml = loader.render_to_string('sitemap.xml', {'urlset': urls})
return HttpResponse(xml, mimetype='application/xml')

View File

@ -7,8 +7,9 @@ from django.db.models import signals
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.contrib.sites import models as site_app from django.contrib.sites import models as site_app
def create_default_site(app, created_models): def create_default_site(app, created_models, verbosity):
if Site in created_models: if Site in created_models:
if verbosity >= 2:
print "Creating example.com Site object" print "Creating example.com Site object"
s = Site(domain="example.com", name="example.com") s = Site(domain="example.com", name="example.com")
s.save() s.save()

View File

@ -48,7 +48,7 @@ def get_cache(backend_uri):
if host.endswith('/'): if host.endswith('/'):
host = host[:-1] host = host[:-1]
cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], '', '', ['']), 'CacheClass') cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], {}, {}, ['']), 'CacheClass')
return cache_class(host, params) return cache_class(host, params)
cache = get_cache(settings.CACHE_BACKEND) cache = get_cache(settings.CACHE_BACKEND)

View File

@ -20,7 +20,7 @@ class CacheClass(BaseCache):
return val return val
def set(self, key, value, timeout=0): def set(self, key, value, timeout=0):
self._cache.set(key, value, timeout) self._cache.set(key, value, timeout or self.default_timeout)
def delete(self, key): def delete(self, key):
self._cache.delete(key) self._cache.delete(key)

View File

@ -51,15 +51,19 @@ def request(request):
class PermLookupDict(object): class PermLookupDict(object):
def __init__(self, user, module_name): def __init__(self, user, module_name):
self.user, self.module_name = user, module_name self.user, self.module_name = user, module_name
def __repr__(self): def __repr__(self):
return str(self.user.get_permission_list()) return str(self.user.get_all_permissions())
def __getitem__(self, perm_name): def __getitem__(self, perm_name):
return self.user.has_perm("%s.%s" % (self.module_name, perm_name)) return self.user.has_perm("%s.%s" % (self.module_name, perm_name))
def __nonzero__(self): def __nonzero__(self):
return self.user.has_module_perms(self.module_name) return self.user.has_module_perms(self.module_name)
class PermWrapper(object): class PermWrapper(object):
def __init__(self, user): def __init__(self, user):
self.user = user self.user = user
def __getitem__(self, module_name): def __getitem__(self, module_name):
return PermLookupDict(self.user, module_name) return PermLookupDict(self.user, module_name)

View File

@ -26,7 +26,7 @@ class BaseHandler(object):
raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:] mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
try: try:
mod = __import__(mw_module, '', '', ['']) mod = __import__(mw_module, {}, {}, [''])
except ImportError, e: except ImportError, e:
raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e) raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
try: try:
@ -48,7 +48,7 @@ class BaseHandler(object):
if hasattr(mw_instance, 'process_exception'): if hasattr(mw_instance, 'process_exception'):
self._exception_middleware.insert(0, mw_instance.process_exception) self._exception_middleware.insert(0, mw_instance.process_exception)
def get_response(self, path, request): def get_response(self, request):
"Returns an HttpResponse object for the given HttpRequest" "Returns an HttpResponse object for the given HttpRequest"
from django.core import exceptions, urlresolvers from django.core import exceptions, urlresolvers
from django.core.mail import mail_admins from django.core.mail import mail_admins
@ -62,7 +62,7 @@ class BaseHandler(object):
resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF) resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
try: try:
callback, callback_args, callback_kwargs = resolver.resolve(path) callback, callback_args, callback_kwargs = resolver.resolve(request.path)
# Apply view middleware # Apply view middleware
for middleware_method in self._view_middleware: for middleware_method in self._view_middleware:
@ -89,7 +89,8 @@ class BaseHandler(object):
return response return response
except http.Http404, e: except http.Http404, e:
if settings.DEBUG: if settings.DEBUG:
return self.get_technical_error_response(request, is404=True, exception=e) from django.views import debug
return debug.technical_404_response(request, e)
else: else:
callback, param_dict = resolver.resolve404() callback, param_dict = resolver.resolve404()
return callback(request, **param_dict) return callback(request, **param_dict)
@ -99,40 +100,24 @@ class BaseHandler(object):
pass # See http://code.djangoproject.com/ticket/1023 pass # See http://code.djangoproject.com/ticket/1023
except: # Handle everything else, including SuspiciousOperation, etc. except: # Handle everything else, including SuspiciousOperation, etc.
if settings.DEBUG: if settings.DEBUG:
return self.get_technical_error_response(request) from django.views import debug
return debug.technical_500_response(request, *sys.exc_info())
else: else:
# Get the exception info now, in case another exception is thrown later. # Get the exception info now, in case another exception is thrown later.
exc_info = sys.exc_info() exc_info = sys.exc_info()
receivers = dispatcher.send(signal=signals.got_request_exception) receivers = dispatcher.send(signal=signals.got_request_exception)
# When DEBUG is False, send an error message to the admins. # When DEBUG is False, send an error message to the admins.
subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', '')) subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
try: try:
request_repr = repr(request) request_repr = repr(request)
except: except:
request_repr = "Request repr() unavailable" request_repr = "Request repr() unavailable"
message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr) message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
mail_admins(subject, message, fail_silently=True) mail_admins(subject, message, fail_silently=True)
return self.get_friendly_error_response(request, resolver) # Return an HttpResponse that displays a friendly error message.
def get_friendly_error_response(self, request, resolver):
"""
Returns an HttpResponse that displays a PUBLIC error message for a
fundamental error.
"""
callback, param_dict = resolver.resolve500() callback, param_dict = resolver.resolve500()
return callback(request, **param_dict) return callback(request, **param_dict)
def get_technical_error_response(self, request, is404=False, exception=None):
"""
Returns an HttpResponse that displays a TECHNICAL error message for a
fundamental error.
"""
from django.views import debug
if is404:
return debug.technical_404_response(request, exception)
else:
return debug.technical_500_response(request, *sys.exc_info())
def _get_traceback(self, exc_info=None): def _get_traceback(self, exc_info=None):
"Helper function to return the traceback as a string" "Helper function to return the traceback as a string"
import traceback import traceback

View File

@ -16,14 +16,32 @@ class ModPythonRequest(http.HttpRequest):
self.path = req.uri self.path = req.uri
def __repr__(self): def __repr__(self):
# Since this is called as part of error handling, we need to be very
# robust against potentially malformed input.
try:
get = pformat(self.GET)
except:
get = '<could not parse>'
try:
post = pformat(self.POST)
except:
post = '<could not parse>'
try:
cookies = pformat(self.COOKIES)
except:
cookies = '<could not parse>'
try:
meta = pformat(self.META)
except:
meta = '<could not parse>'
return '<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \ return '<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
(self.path, pformat(self.GET), pformat(self.POST), pformat(self.COOKIES), (self.path, get, post, cookies, meta)
pformat(self.META))
def get_full_path(self): def get_full_path(self):
return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '') return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
def is_secure(self): def is_secure(self):
# Note: modpython 3.2.10+ has req.is_https(), but we need to support previous versions
return self._req.subprocess_env.has_key('HTTPS') and self._req.subprocess_env['HTTPS'] == 'on' return self._req.subprocess_env.has_key('HTTPS') and self._req.subprocess_env['HTTPS'] == 'on'
def _load_post_and_files(self): def _load_post_and_files(self):
@ -122,10 +140,6 @@ class ModPythonHandler(BaseHandler):
# that use settings now can work # that use settings now can work
from django.conf import settings from django.conf import settings
if settings.ENABLE_PSYCO:
import psyco
psyco.profile()
# if we need to set up middleware, now that settings works we can do it now. # if we need to set up middleware, now that settings works we can do it now.
if self._request_middleware is None: if self._request_middleware is None:
self.load_middleware() self.load_middleware()
@ -133,7 +147,7 @@ class ModPythonHandler(BaseHandler):
dispatcher.send(signal=signals.request_started) dispatcher.send(signal=signals.request_started)
try: try:
request = ModPythonRequest(req) request = ModPythonRequest(req)
response = self.get_response(req.uri, request) response = self.get_response(request)
# Apply response middleware # Apply response middleware
for middleware_method in self._response_middleware: for middleware_method in self._response_middleware:
@ -143,20 +157,20 @@ class ModPythonHandler(BaseHandler):
dispatcher.send(signal=signals.request_finished) dispatcher.send(signal=signals.request_finished)
# Convert our custom HttpResponse object back into the mod_python req. # Convert our custom HttpResponse object back into the mod_python req.
populate_apache_request(response, req) req.content_type = response['Content-Type']
return 0 # mod_python.apache.OK for key, value in response.headers.items():
def populate_apache_request(http_response, mod_python_req):
"Populates the mod_python request object with an HttpResponse"
mod_python_req.content_type = http_response['Content-Type']
for key, value in http_response.headers.items():
if key != 'Content-Type': if key != 'Content-Type':
mod_python_req.headers_out[key] = value req.headers_out[key] = value
for c in http_response.cookies.values(): for c in response.cookies.values():
mod_python_req.headers_out.add('Set-Cookie', c.output(header='')) req.headers_out.add('Set-Cookie', c.output(header=''))
mod_python_req.status = http_response.status_code req.status = response.status_code
for chunk in http_response.iterator: try:
mod_python_req.write(chunk) for chunk in response:
req.write(chunk)
finally:
response.close()
return 0 # mod_python.apache.OK
def handler(req): def handler(req):
# mod_python hooks into this function. # mod_python hooks into this function.

View File

@ -4,6 +4,11 @@ from django.dispatch import dispatcher
from django.utils import datastructures from django.utils import datastructures
from django import http from django import http
from pprint import pformat from pprint import pformat
from shutil import copyfileobj
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
STATUS_CODE_TEXT = { STATUS_CODE_TEXT = {
@ -50,6 +55,21 @@ STATUS_CODE_TEXT = {
505: 'HTTP VERSION NOT SUPPORTED', 505: 'HTTP VERSION NOT SUPPORTED',
} }
def safe_copyfileobj(fsrc, fdst, length=16*1024, size=0):
"""
A version of shutil.copyfileobj that will not read more than 'size' bytes.
This makes it safe from clients sending more than CONTENT_LENGTH bytes of
data in the body.
"""
if not size:
return copyfileobj(fsrc, fdst, length)
while size > 0:
buf = fsrc.read(min(length, size))
if not buf:
break
fdst.write(buf)
size -= len(buf)
class WSGIRequest(http.HttpRequest): class WSGIRequest(http.HttpRequest):
def __init__(self, environ): def __init__(self, environ):
self.environ = environ self.environ = environ
@ -58,9 +78,26 @@ class WSGIRequest(http.HttpRequest):
self.method = environ['REQUEST_METHOD'].upper() self.method = environ['REQUEST_METHOD'].upper()
def __repr__(self): def __repr__(self):
# Since this is called as part of error handling, we need to be very
# robust against potentially malformed input.
try:
get = pformat(self.GET)
except:
get = '<could not parse>'
try:
post = pformat(self.POST)
except:
post = '<could not parse>'
try:
cookies = pformat(self.COOKIES)
except:
cookies = '<could not parse>'
try:
meta = pformat(self.META)
except:
meta = '<could not parse>'
return '<WSGIRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \ return '<WSGIRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
(pformat(self.GET), pformat(self.POST), pformat(self.COOKIES), (get, post, cookies, meta)
pformat(self.META))
def get_full_path(self): def get_full_path(self):
return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '') return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')
@ -119,7 +156,11 @@ class WSGIRequest(http.HttpRequest):
try: try:
return self._raw_post_data return self._raw_post_data
except AttributeError: except AttributeError:
self._raw_post_data = self.environ['wsgi.input'].read(int(self.environ["CONTENT_LENGTH"])) buf = StringIO()
content_length = int(self.environ['CONTENT_LENGTH'])
safe_copyfileobj(self.environ['wsgi.input'], buf, size=content_length)
self._raw_post_data = buf.getvalue()
buf.close()
return self._raw_post_data return self._raw_post_data
GET = property(_get_get, _set_get) GET = property(_get_get, _set_get)
@ -133,10 +174,6 @@ class WSGIHandler(BaseHandler):
def __call__(self, environ, start_response): def __call__(self, environ, start_response):
from django.conf import settings from django.conf import settings
if settings.ENABLE_PSYCO:
import psyco
psyco.profile()
# Set up middleware if needed. We couldn't do this earlier, because # Set up middleware if needed. We couldn't do this earlier, because
# settings weren't available. # settings weren't available.
if self._request_middleware is None: if self._request_middleware is None:
@ -145,7 +182,7 @@ class WSGIHandler(BaseHandler):
dispatcher.send(signal=signals.request_started) dispatcher.send(signal=signals.request_started)
try: try:
request = WSGIRequest(environ) request = WSGIRequest(environ)
response = self.get_response(request.path, request) response = self.get_response(request)
# Apply response middleware # Apply response middleware
for middleware_method in self._response_middleware: for middleware_method in self._response_middleware:
@ -163,4 +200,4 @@ class WSGIHandler(BaseHandler):
for c in response.cookies.values(): for c in response.cookies.values():
response_headers.append(('Set-Cookie', c.output(header=''))) response_headers.append(('Set-Cookie', c.output(header='')))
start_response(status, response_headers) start_response(status, response_headers)
return response.iterator return response

View File

@ -32,6 +32,7 @@ class dummy: pass
style = dummy() style = dummy()
style.ERROR = termcolors.make_style(fg='red', opts=('bold',)) style.ERROR = termcolors.make_style(fg='red', opts=('bold',))
style.ERROR_OUTPUT = termcolors.make_style(fg='red', opts=('bold',)) style.ERROR_OUTPUT = termcolors.make_style(fg='red', opts=('bold',))
style.NOTICE = termcolors.make_style(fg='red')
style.SQL_FIELD = termcolors.make_style(fg='green', opts=('bold',)) style.SQL_FIELD = termcolors.make_style(fg='green', opts=('bold',))
style.SQL_COLTYPE = termcolors.make_style(fg='green') style.SQL_COLTYPE = termcolors.make_style(fg='green')
style.SQL_KEYWORD = termcolors.make_style(fg='yellow') style.SQL_KEYWORD = termcolors.make_style(fg='yellow')
@ -94,12 +95,14 @@ def get_sql_create(app):
"Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n")) "Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n"))
sys.exit(1) sys.exit(1)
# Get installed models, so we generate REFERENCES right # Get installed models, so we generate REFERENCES right.
final_output = [] # We trim models from the current app so that the sqlreset command does not
known_models = set(_get_installed_models(_get_table_list())) # generate invalid SQL (leaving models out of known_models is harmless, so
pending_references = {} # we can be conservative).
app_models = models.get_models(app) app_models = models.get_models(app)
final_output = []
known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models])
pending_references = {}
for model in app_models: for model in app_models:
output, references = _get_sql_model_create(model, known_models) output, references = _get_sql_model_create(model, known_models)
@ -118,10 +121,13 @@ def get_sql_create(app):
# but don't exist physically # but don't exist physically
not_installed_models = set(pending_references.keys()) not_installed_models = set(pending_references.keys())
if not_installed_models: if not_installed_models:
final_output.append('-- The following references should be added but depend on non-existant tables:') alter_sql = []
for model in not_installed_models: for model in not_installed_models:
final_output.extend(['-- ' + sql for sql in alter_sql.extend(['-- ' + sql for sql in
_get_sql_for_pending_references(model, pending_references)]) _get_sql_for_pending_references(model, pending_references)])
if alter_sql:
final_output.append('-- The following references should be added but depend on non-existent tables:')
final_output.extend(alter_sql)
return final_output return final_output
get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)." get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)."
@ -141,7 +147,7 @@ def _get_sql_model_create(model, known_models=set()):
table_output = [] table_output = []
pending_references = {} pending_references = {}
for f in opts.fields: for f in opts.fields:
if isinstance(f, models.ForeignKey): if isinstance(f, (models.ForeignKey, models.OneToOneField)):
rel_field = f.rel.get_related_field() rel_field = f.rel.get_related_field()
data_type = get_rel_data_type(rel_field) data_type = get_rel_data_type(rel_field)
else: else:
@ -295,7 +301,7 @@ def get_sql_delete(app):
(style.SQL_KEYWORD('ALTER TABLE'), (style.SQL_KEYWORD('ALTER TABLE'),
style.SQL_TABLE(backend.quote_name(table)), style.SQL_TABLE(backend.quote_name(table)),
style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()), style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
style.SQL_FIELD(backend.quote_name("%s_referencing_%s_%s" % (col, r_table, r_col))))) style.SQL_FIELD(backend.quote_name('%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table))))))))
del references_to_delete[model] del references_to_delete[model]
# Output DROP TABLE statements for many-to-many tables. # Output DROP TABLE statements for many-to-many tables.
@ -341,7 +347,7 @@ def get_sql_initial_data_for_model(model):
os.path.join(app_dir, "%s.sql" % opts.object_name.lower())] os.path.join(app_dir, "%s.sql" % opts.object_name.lower())]
for sql_file in sql_files: for sql_file in sql_files:
if os.path.exists(sql_file): if os.path.exists(sql_file):
fp = open(sql_file) fp = open(sql_file, 'U')
for statement in statements.split(fp.read()): for statement in statements.split(fp.read()):
if statement.strip(): if statement.strip():
output.append(statement + ";") output.append(statement + ";")
@ -392,11 +398,20 @@ get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting Postg
get_sql_sequence_reset.args = APP_ARGS get_sql_sequence_reset.args = APP_ARGS
def get_sql_indexes(app): def get_sql_indexes(app):
"Returns a list of the CREATE INDEX SQL statements for the given app." "Returns a list of the CREATE INDEX SQL statements for all models in the given app."
from django.db import backend, models from django.db import models
output = []
for model in models.get_models(app):
output.extend(get_sql_indexes_for_model(model))
return output
get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
get_sql_indexes.args = APP_ARGS
def get_sql_indexes_for_model(model):
"Returns the CREATE INDEX SQL statements for a single model"
from django.db import backend
output = [] output = []
for model in models.get_models(app):
for f in model._meta.fields: for f in model._meta.fields:
if f.db_index: if f.db_index:
unique = f.unique and 'UNIQUE ' or '' unique = f.unique and 'UNIQUE ' or ''
@ -408,8 +423,6 @@ def get_sql_indexes(app):
"(%s);" % style.SQL_FIELD(backend.quote_name(f.column)) "(%s);" % style.SQL_FIELD(backend.quote_name(f.column))
) )
return output return output
get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
get_sql_indexes.args = APP_ARGS
def get_sql_all(app): def get_sql_all(app):
"Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module." "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
@ -417,7 +430,7 @@ def get_sql_all(app):
get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)." get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
get_sql_all.args = APP_ARGS get_sql_all.args = APP_ARGS
def syncdb(): def syncdb(verbosity=1, interactive=True):
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
from django.db import connection, transaction, models, get_creation_module from django.db import connection, transaction, models, get_creation_module
from django.db.models import signals from django.db.models import signals
@ -433,7 +446,7 @@ def syncdb():
# dispatcher events. # dispatcher events.
for app_name in settings.INSTALLED_APPS: for app_name in settings.INSTALLED_APPS:
try: try:
__import__(app_name + '.management', '', '', ['']) __import__(app_name + '.management', {}, {}, [''])
except ImportError: except ImportError:
pass pass
@ -451,20 +464,21 @@ def syncdb():
pending_references = {} pending_references = {}
for app in models.get_apps(): for app in models.get_apps():
app_name = app.__name__.split('.')[-2]
model_list = models.get_models(app) model_list = models.get_models(app)
for model in model_list: for model in model_list:
# Create the model's database table, if it doesn't already exist. # Create the model's database table, if it doesn't already exist.
if verbosity >= 2:
print "Processing %s.%s model" % (app_name, model._meta.object_name)
if model._meta.db_table in table_list: if model._meta.db_table in table_list:
continue continue
sql, references = _get_sql_model_create(model, seen_models) sql, references = _get_sql_model_create(model, seen_models)
seen_models.add(model) seen_models.add(model)
created_models.add(model) created_models.add(model)
for refto, refs in references.items(): for refto, refs in references.items():
try: pending_references.setdefault(refto, []).extend(refs)
pending_references[refto].extend(refs)
except KeyError:
pending_references[refto] = refs
sql.extend(_get_sql_for_pending_references(model, pending_references)) sql.extend(_get_sql_for_pending_references(model, pending_references))
if verbosity >= 1:
print "Creating table %s" % model._meta.db_table print "Creating table %s" % model._meta.db_table
for statement in sql: for statement in sql:
cursor.execute(statement) cursor.execute(statement)
@ -474,7 +488,8 @@ def syncdb():
if model in created_models: if model in created_models:
sql = _get_many_to_many_sql_for_model(model) sql = _get_many_to_many_sql_for_model(model)
if sql: if sql:
print "Creating many-to-many tables for %s model" % model.__name__ if verbosity >= 2:
print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)
for statement in sql: for statement in sql:
cursor.execute(statement) cursor.execute(statement)
@ -483,8 +498,12 @@ def syncdb():
# Send the post_syncdb signal, so individual apps can do whatever they need # Send the post_syncdb signal, so individual apps can do whatever they need
# to do at this point. # to do at this point.
for app in models.get_apps(): for app in models.get_apps():
app_name = app.__name__.split('.')[-2]
if verbosity >= 2:
print "Running post-sync handlers for application", app_name
dispatcher.send(signal=signals.post_syncdb, sender=app, dispatcher.send(signal=signals.post_syncdb, sender=app,
app=app, created_models=created_models) app=app, created_models=created_models,
verbosity=verbosity, interactive=interactive)
# Install initial data for the app (but only if this is a model we've # Install initial data for the app (but only if this is a model we've
# just created) # just created)
@ -492,13 +511,33 @@ def syncdb():
if model in created_models: if model in created_models:
initial_sql = get_sql_initial_data_for_model(model) initial_sql = get_sql_initial_data_for_model(model)
if initial_sql: if initial_sql:
print "Installing initial data for %s model" % model._meta.object_name if verbosity >= 1:
print "Installing initial data for %s.%s model" % (app_name, model._meta.object_name)
try: try:
for sql in initial_sql: for sql in initial_sql:
cursor.execute(sql) cursor.execute(sql)
except Exception, e: except Exception, e:
sys.stderr.write("Failed to install initial SQL data for %s model: %s" % \ sys.stderr.write("Failed to install initial SQL data for %s.%s model: %s" % \
(model._meta.object_name, e)) (app_name, model._meta.object_name, e))
transaction.rollback_unless_managed()
else:
transaction.commit_unless_managed()
# Install SQL indicies for all newly created models
for app in models.get_apps():
app_name = app.__name__.split('.')[-2]
for model in models.get_models(app):
if model in created_models:
index_sql = get_sql_indexes_for_model(model)
if index_sql:
if verbosity >= 1:
print "Installing index for %s.%s model" % (app_name, model._meta.object_name)
try:
for sql in index_sql:
cursor.execute(sql)
except Exception, e:
sys.stderr.write("Failed to install index for %s.%s model: %s" % \
(app_name, model._meta.object_name, e))
transaction.rollback_unless_managed() transaction.rollback_unless_managed()
else: else:
transaction.commit_unless_managed() transaction.commit_unless_managed()
@ -542,7 +581,7 @@ def diffsettings():
# Inspired by Postfix's "postconf -n". # Inspired by Postfix's "postconf -n".
from django.conf import settings, global_settings from django.conf import settings, global_settings
user_settings = _module_to_dict(settings) user_settings = _module_to_dict(settings._target)
default_settings = _module_to_dict(global_settings) default_settings = _module_to_dict(global_settings)
output = [] output = []
@ -586,9 +625,10 @@ The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database." install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database."
install.args = APP_ARGS install.args = APP_ARGS
def reset(app): def reset(app, interactive=True):
"Executes the equivalent of 'get_sql_reset' in the current database." "Executes the equivalent of 'get_sql_reset' in the current database."
from django.db import connection, transaction from django.db import connection, transaction
from django.conf import settings
app_name = app.__name__.split('.')[-2] app_name = app.__name__.split('.')[-2]
disable_termcolors() disable_termcolors()
@ -597,21 +637,26 @@ def reset(app):
_check_for_validation_errors(app) _check_for_validation_errors(app)
sql_list = get_sql_reset(app) sql_list = get_sql_reset(app)
if interactive:
confirm = raw_input(""" confirm = raw_input("""
You have requested a database reset. You have requested a database reset.
This will IRREVERSIBLY DESTROY any data in your database. This will IRREVERSIBLY DESTROY any data for
the "%s" application in the database "%s".
Are you sure you want to do this? Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: """) Type 'yes' to continue, or 'no' to cancel: """ % (app_name, settings.DATABASE_NAME))
else:
confirm = 'yes'
if confirm == 'yes': if confirm == 'yes':
try: try:
cursor = connection.cursor() cursor = connection.cursor()
for sql in sql_list: for sql in sql_list:
cursor.execute(sql) cursor.execute(sql)
except Exception, e: except Exception, e:
sys.stderr.write(style.ERROR("""Error: %s couldn't be installed. Possible reasons: sys.stderr.write(style.ERROR("""Error: %s couldn't be reset. Possible reasons:
* The database isn't running or isn't configured correctly. * The database isn't running or isn't configured correctly.
* At least one of the database tables already exists. * At least one of the database tables doesn't exist.
* The SQL was invalid. * The SQL was invalid.
Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run. Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run.
The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n') The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
@ -652,7 +697,10 @@ def _start_helper(app_or_project, name, directory, other_name=''):
fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name)) fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
fp_old.close() fp_old.close()
fp_new.close() fp_new.close()
try:
shutil.copymode(path_old, path_new) shutil.copymode(path_old, path_new)
except OSError:
sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))
def startproject(project_name, directory): def startproject(project_name, directory):
"Creates a Django project for the given project_name in the given directory." "Creates a Django project for the given project_name in the given directory."
@ -692,9 +740,7 @@ def inspectdb():
introspection_module = get_introspection_module() introspection_module = get_introspection_module()
def table2model(table_name): table2model = lambda table_name: table_name.title().replace('_', '')
object_name = table_name.title().replace('_', '')
return object_name.endswith('s') and object_name[:-1] or object_name
cursor = connection.cursor() cursor = connection.cursor()
yield "# This is an auto-generated Django model module." yield "# This is an auto-generated Django model module."
@ -723,6 +769,10 @@ def inspectdb():
comment_notes = [] # Holds Field notes, to be displayed in a Python comment. comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
extra_params = {} # Holds Field parameters such as 'db_column'. extra_params = {} # Holds Field parameters such as 'db_column'.
if ' ' in att_name:
extra_params['db_column'] = att_name
att_name = att_name.replace(' ', '')
comment_notes.append('Field renamed to remove spaces.')
if keyword.iskeyword(att_name): if keyword.iskeyword(att_name):
extra_params['db_column'] = att_name extra_params['db_column'] = att_name
att_name += '_field' att_name += '_field'
@ -808,7 +858,8 @@ def get_validation_errors(outfile, app=None):
validates all models of all installed apps. Writes errors, if any, to outfile. validates all models of all installed apps. Writes errors, if any, to outfile.
Returns number of errors. Returns number of errors.
""" """
from django.db import models from django.conf import settings
from django.db import models, connection
from django.db.models.loading import get_app_errors from django.db.models.loading import get_app_errors
from django.db.models.fields.related import RelatedObject from django.db.models.fields.related import RelatedObject
@ -850,6 +901,12 @@ def get_validation_errors(outfile, app=None):
if f.db_index not in (None, True, False): if f.db_index not in (None, True, False):
e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name) e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)
# Check that maxlength <= 255 if using older MySQL versions.
if settings.DATABASE_ENGINE == 'mysql':
db_version = connection.get_server_version()
if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255:
e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]])))
# Check to see if the related field will clash with any # Check to see if the related field will clash with any
# existing fields, m2m fields, m2m related objects or related objects # existing fields, m2m fields, m2m related objects or related objects
if f.rel: if f.rel:
@ -891,6 +948,11 @@ def get_validation_errors(outfile, app=None):
rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
rel_query_name = f.related_query_name() rel_query_name = f.related_query_name()
# If rel_name is none, there is no reverse accessor.
# (This only occurs for symmetrical m2m relations to self).
# If this is the case, there are no clashes to check for this field, as
# there are no reverse descriptors for this field.
if rel_name is not None:
for r in rel_opts.fields: for r in rel_opts.fields:
if r.name == rel_name: if r.name == rel_name:
e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
@ -941,7 +1003,8 @@ def get_validation_errors(outfile, app=None):
try: try:
f = opts.get_field(fn) f = opts.get_field(fn)
except models.FieldDoesNotExist: except models.FieldDoesNotExist:
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn) if not hasattr(cls, fn):
e.add(opts, '"admin.list_display_links" refers to %r, which isn\'t an attribute, method or property.' % fn)
if fn not in opts.admin.list_display: if fn not in opts.admin.list_display:
e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn) e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn)
# list_filter # list_filter
@ -999,10 +1062,12 @@ def get_validation_errors(outfile, app=None):
return len(e.errors) return len(e.errors)
def validate(outfile=sys.stdout): def validate(outfile=sys.stdout, silent_success=False):
"Validates all installed models." "Validates all installed models."
try: try:
num_errors = get_validation_errors(outfile) num_errors = get_validation_errors(outfile)
if silent_success and num_errors == 0:
return
outfile.write('%s error%s found.\n' % (num_errors, num_errors != 1 and 's' or '')) outfile.write('%s error%s found.\n' % (num_errors, num_errors != 1 and 's' or ''))
except ImproperlyConfigured: except ImproperlyConfigured:
outfile.write("Skipping validation because things aren't configured properly.") outfile.write("Skipping validation because things aren't configured properly.")
@ -1025,7 +1090,7 @@ def _check_for_validation_errors(app=None):
sys.stderr.write(s.read()) sys.stderr.write(s.read())
sys.exit(1) sys.exit(1)
def runserver(addr, port, use_reloader=True): def runserver(addr, port, use_reloader=True, admin_media_dir=''):
"Starts a lightweight Web server for development." "Starts a lightweight Web server for development."
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
from django.core.handlers.wsgi import WSGIHandler from django.core.handlers.wsgi import WSGIHandler
@ -1043,7 +1108,10 @@ def runserver(addr, port, use_reloader=True):
print "Development server is running at http://%s:%s/" % (addr, port) print "Development server is running at http://%s:%s/" % (addr, port)
print "Quit the server with %s." % quit_command print "Quit the server with %s." % quit_command
try: try:
run(addr, int(port), AdminMediaHandler(WSGIHandler())) import django
path = admin_media_dir or django.__path__[0] + '/contrib/admin/media'
handler = AdminMediaHandler(WSGIHandler(), path)
run(addr, int(port), handler)
except WSGIServerException, e: except WSGIServerException, e:
# Use helpful error messages instead of ugly tracebacks. # Use helpful error messages instead of ugly tracebacks.
ERRORS = { ERRORS = {
@ -1064,7 +1132,7 @@ def runserver(addr, port, use_reloader=True):
autoreload.main(inner_run) autoreload.main(inner_run)
else: else:
inner_run() inner_run()
runserver.args = '[--noreload] [optional port number, or ipaddr:port]' runserver.args = '[--noreload] [--adminmedia=ADMIN_MEDIA_PATH] [optional port number, or ipaddr:port]'
def createcachetable(tablename): def createcachetable(tablename):
"Creates the table needed to use the SQL cache backend" "Creates the table needed to use the SQL cache backend"
@ -1134,11 +1202,41 @@ def dbshell():
dbshell.args = "" dbshell.args = ""
def runfcgi(args): def runfcgi(args):
"""Run this project as a FastCGI application. requires flup.""" "Runs this project as a FastCGI application. Requires flup."
from django.conf import settings
from django.utils import translation
# Activate the current language, because it won't get activated later.
try:
translation.activate(settings.LANGUAGE_CODE)
except AttributeError:
pass
from django.core.servers.fastcgi import runfastcgi from django.core.servers.fastcgi import runfastcgi
runfastcgi(args) runfastcgi(args)
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]' runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
def test(app_labels, verbosity=1):
"Runs the test suite for the specified applications"
from django.conf import settings
from django.db.models import get_app, get_apps
if len(app_labels) == 0:
app_list = get_apps()
else:
app_list = [get_app(app_label) for app_label in app_labels]
test_path = settings.TEST_RUNNER.split('.')
# Allow for Python 2.5 relative paths
if len(test_path) > 1:
test_module_name = '.'.join(test_path[:-1])
else:
test_module_name = '.'
test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1])
test_runner(app_list, verbosity)
test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
test.args = '[--verbosity] ' + APP_ARGS
# Utilities for command-line script # Utilities for command-line script
DEFAULT_ACTION_MAPPING = { DEFAULT_ACTION_MAPPING = {
@ -1163,6 +1261,7 @@ DEFAULT_ACTION_MAPPING = {
'startproject': startproject, 'startproject': startproject,
'syncdb': syncdb, 'syncdb': syncdb,
'validate': validate, 'validate': validate,
'test':test,
} }
NO_SQL_TRANSACTION = ( NO_SQL_TRANSACTION = (
@ -1213,8 +1312,15 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".') help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
parser.add_option('--plain', action='store_true', dest='plain', parser.add_option('--plain', action='store_true', dest='plain',
help='Tells Django to use plain Python, not IPython, for "shell" command.') help='Tells Django to use plain Python, not IPython, for "shell" command.')
parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.')
parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True, parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
help='Tells Django to NOT use the auto-reloader when running the development server.') help='Tells Django to NOT use the auto-reloader when running the development server.')
parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
type='choice', choices=['0', '1', '2'],
help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
parser.add_option('--adminmedia', dest='admin_media_path', default='', help='Specifies the directory from which to serve admin media for runserver.'),
options, args = parser.parse_args(argv[1:]) options, args = parser.parse_args(argv[1:])
# Take care of options. # Take care of options.
@ -1241,8 +1347,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
if action == 'shell': if action == 'shell':
action_mapping[action](options.plain is True) action_mapping[action](options.plain is True)
elif action in ('syncdb', 'validate', 'diffsettings', 'dbshell'): elif action in ('validate', 'diffsettings', 'dbshell'):
action_mapping[action]() action_mapping[action]()
elif action == 'syncdb':
action_mapping[action](int(options.verbosity), options.interactive)
elif action == 'inspectdb': elif action == 'inspectdb':
try: try:
for line in action_mapping[action](): for line in action_mapping[action]():
@ -1255,6 +1363,11 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
action_mapping[action](args[1]) action_mapping[action](args[1])
except IndexError: except IndexError:
parser.print_usage_and_exit() parser.print_usage_and_exit()
elif action == 'test':
try:
action_mapping[action](args[1:], int(options.verbosity))
except IndexError:
parser.print_usage_and_exit()
elif action in ('startapp', 'startproject'): elif action in ('startapp', 'startproject'):
try: try:
name = args[1] name = args[1]
@ -1270,11 +1383,12 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
addr, port = args[1].split(':') addr, port = args[1].split(':')
except ValueError: except ValueError:
addr, port = '', args[1] addr, port = '', args[1]
action_mapping[action](addr, port, options.use_reloader) action_mapping[action](addr, port, options.use_reloader, options.admin_media_path)
elif action == 'runfcgi': elif action == 'runfcgi':
action_mapping[action](args[1:]) action_mapping[action](args[1:])
else: else:
from django.db import models from django.db import models
validate(silent_success=True)
try: try:
mod_list = [models.get_app(app_label) for app_label in args[1:]] mod_list = [models.get_app(app_label) for app_label in args[1:]]
except ImportError, e: except ImportError, e:
@ -1285,25 +1399,35 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
if action not in NO_SQL_TRANSACTION: if action not in NO_SQL_TRANSACTION:
print style.SQL_KEYWORD("BEGIN;") print style.SQL_KEYWORD("BEGIN;")
for mod in mod_list: for mod in mod_list:
if action == 'reset':
output = action_mapping[action](mod, options.interactive)
else:
output = action_mapping[action](mod) output = action_mapping[action](mod)
if output: if output:
print '\n'.join(output) print '\n'.join(output)
if action not in NO_SQL_TRANSACTION: if action not in NO_SQL_TRANSACTION:
print style.SQL_KEYWORD("COMMIT;") print style.SQL_KEYWORD("COMMIT;")
def execute_manager(settings_mod, argv=None): def setup_environ(settings_mod):
"""
Configure the runtime environment. This can also be used by external
scripts wanting to set up a similar environment to manage.py.
"""
# Add this project to sys.path so that it's importable in the conventional # Add this project to sys.path so that it's importable in the conventional
# way. For example, if this file (manage.py) lives in a directory # way. For example, if this file (manage.py) lives in a directory
# "myproject", this code would add "/path/to/myproject" to sys.path. # "myproject", this code would add "/path/to/myproject" to sys.path.
project_directory = os.path.dirname(settings_mod.__file__) project_directory = os.path.dirname(settings_mod.__file__)
project_name = os.path.basename(project_directory) project_name = os.path.basename(project_directory)
sys.path.append(os.path.join(project_directory, '..')) sys.path.append(os.path.join(project_directory, '..'))
project_module = __import__(project_name, '', '', ['']) project_module = __import__(project_name, {}, {}, [''])
sys.path.pop() sys.path.pop()
# Set DJANGO_SETTINGS_MODULE appropriately. # Set DJANGO_SETTINGS_MODULE appropriately.
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
return project_directory
def execute_manager(settings_mod, argv=None):
project_directory = setup_environ(settings_mod)
action_mapping = DEFAULT_ACTION_MAPPING.copy() action_mapping = DEFAULT_ACTION_MAPPING.copy()
# Remove the "startproject" command from the action_mapping, because that's # Remove the "startproject" command from the action_mapping, because that's

View File

@ -29,7 +29,7 @@ _serializers = {}
def register_serializer(format, serializer_module): def register_serializer(format, serializer_module):
"""Register a new serializer by passing in a module name.""" """Register a new serializer by passing in a module name."""
module = __import__(serializer_module, '', '', ['']) module = __import__(serializer_module, {}, {}, [''])
_serializers[format] = module _serializers[format] = module
def unregister_serializer(format): def unregister_serializer(format):

View File

@ -50,7 +50,11 @@ class Serializer(object):
Convert a field's value to a string. Convert a field's value to a string.
""" """
if isinstance(field, models.DateTimeField): if isinstance(field, models.DateTimeField):
value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S") value = getattr(obj, field.name)
if value is None:
value = ''
else:
value = value.strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(field, models.FileField): elif isinstance(field, models.FileField):
value = getattr(obj, "get_%s_url" % field.name, lambda: None)() value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
else: else:

View File

@ -16,7 +16,7 @@ class Serializer(PythonSerializer):
Convert a queryset to JSON. Convert a queryset to JSON.
""" """
def end_serialization(self): def end_serialization(self):
simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder) simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder, **self.options)
def getvalue(self): def getvalue(self):
return self.stream.getvalue() return self.stream.getvalue()
@ -48,4 +48,4 @@ class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
elif isinstance(o, datetime.time): elif isinstance(o, datetime.time):
return o.strftime(self.TIME_FORMAT) return o.strftime(self.TIME_FORMAT)
else: else:
return super(self, DateTimeAwareJSONEncoder).default(o) return super(DateTimeAwareJSONEncoder, self).default(o)

View File

@ -547,10 +547,6 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
env['PATH_INFO'] = urllib.unquote(path) env['PATH_INFO'] = urllib.unquote(path)
env['QUERY_STRING'] = query env['QUERY_STRING'] = query
host = self.address_string()
if host != self.client_address[0]:
env['REMOTE_HOST'] = host
env['REMOTE_ADDR'] = self.client_address[0] env['REMOTE_ADDR'] = self.client_address[0]
if self.headers.typeheader is None: if self.headers.typeheader is None:
@ -598,11 +594,14 @@ class AdminMediaHandler(object):
Use this ONLY LOCALLY, for development! This hasn't been tested for Use this ONLY LOCALLY, for development! This hasn't been tested for
security and is not super efficient. security and is not super efficient.
""" """
def __init__(self, application): def __init__(self, application, media_dir=None):
from django.conf import settings from django.conf import settings
import django
self.application = application self.application = application
if not media_dir:
import django
self.media_dir = django.__path__[0] + '/contrib/admin/media' self.media_dir = django.__path__[0] + '/contrib/admin/media'
else:
self.media_dir = media_dir
self.media_url = settings.ADMIN_MEDIA_PREFIX self.media_url = settings.ADMIN_MEDIA_PREFIX
def __call__(self, environ, start_response): def __call__(self, environ, start_response):

View File

@ -31,6 +31,8 @@ Optional Fcgi settings: (setting=value)
port=PORTNUM port to listen on. port=PORTNUM port to listen on.
socket=FILE UNIX socket to listen on. socket=FILE UNIX socket to listen on.
method=IMPL prefork or threaded (default prefork) method=IMPL prefork or threaded (default prefork)
maxrequests=NUMBER number of requests a child handles before it is
killed and a new child is forked (0 = no limit).
maxspare=NUMBER max number of spare processes to keep running. maxspare=NUMBER max number of spare processes to keep running.
minspare=NUMBER min number of spare processes to prefork. minspare=NUMBER min number of spare processes to prefork.
maxchildren=NUMBER hard limit number of processes in prefork mode. maxchildren=NUMBER hard limit number of processes in prefork mode.
@ -66,6 +68,7 @@ FASTCGI_OPTIONS = {
'maxspare': 5, 'maxspare': 5,
'minspare': 2, 'minspare': 2,
'maxchildren': 50, 'maxchildren': 50,
'maxrequests': 0,
} }
def fastcgi_help(message=None): def fastcgi_help(message=None):
@ -74,8 +77,9 @@ def fastcgi_help(message=None):
print message print message
return False return False
def runfastcgi(argset): def runfastcgi(argset=[], **kwargs):
options = FASTCGI_OPTIONS.copy() options = FASTCGI_OPTIONS.copy()
options.update(kwargs)
for x in argset: for x in argset:
if "=" in x: if "=" in x:
k, v = x.split('=', 1) k, v = x.split('=', 1)
@ -102,6 +106,7 @@ def runfastcgi(argset):
'maxSpare': int(options["maxspare"]), 'maxSpare': int(options["maxspare"]),
'minSpare': int(options["minspare"]), 'minSpare': int(options["minspare"]),
'maxChildren': int(options["maxchildren"]), 'maxChildren': int(options["maxchildren"]),
'maxRequests': int(options["maxrequests"]),
} }
elif options['method'] in ('thread', 'threaded'): elif options['method'] in ('thread', 'threaded'):
from flup.server.fcgi import WSGIServer from flup.server.fcgi import WSGIServer

View File

@ -15,7 +15,8 @@ class Resolver404(Http404):
pass pass
class NoReverseMatch(Exception): class NoReverseMatch(Exception):
pass # Don't make this raise an error when used in a template.
silent_variable_failure = True
def get_mod_func(callback): def get_mod_func(callback):
# Converts 'django.views.news.stories.story_detail' to # Converts 'django.views.news.stories.story_detail' to
@ -86,10 +87,15 @@ class MatchChecker(object):
class RegexURLPattern(object): class RegexURLPattern(object):
def __init__(self, regex, callback, default_args=None): def __init__(self, regex, callback, default_args=None):
# regex is a string representing a regular expression. # regex is a string representing a regular expression.
# callback is something like 'foo.views.news.stories.story_detail', # callback is either a string like 'foo.views.news.stories.story_detail'
# which represents the path to a module and a view function name. # which represents the path to a module and a view function name, or a
# callable object (view).
self.regex = re.compile(regex) self.regex = re.compile(regex)
self.callback = callback if callable(callback):
self._callback = callback
else:
self._callback = None
self._callback_str = callback
self.default_args = default_args or {} self.default_args = default_args or {}
def resolve(self, path): def resolve(self, path):
@ -106,23 +112,28 @@ class RegexURLPattern(object):
# In both cases, pass any extra_kwargs as **kwargs. # In both cases, pass any extra_kwargs as **kwargs.
kwargs.update(self.default_args) kwargs.update(self.default_args)
try: # Lazily load self.func. return self.callback, args, kwargs
return self.func, args, kwargs
except AttributeError:
self.func = self.get_callback()
return self.func, args, kwargs
def get_callback(self): def _get_callback(self):
mod_name, func_name = get_mod_func(self.callback) if self._callback is not None:
return self._callback
mod_name, func_name = get_mod_func(self._callback_str)
try: try:
return getattr(__import__(mod_name, '', '', ['']), func_name) self._callback = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except ImportError, e: except ImportError, e:
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e)) raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
except AttributeError, e: except AttributeError, e:
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e)) raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
return self._callback
callback = property(_get_callback)
def reverse(self, viewname, *args, **kwargs): def reverse(self, viewname, *args, **kwargs):
if viewname != self.callback: mod_name, func_name = get_mod_func(viewname)
try:
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError):
raise NoReverseMatch
if lookup_view != self.callback:
raise NoReverseMatch raise NoReverseMatch
return self.reverse_helper(*args, **kwargs) return self.reverse_helper(*args, **kwargs)
@ -160,7 +171,7 @@ class RegexURLResolver(object):
return self._urlconf_module return self._urlconf_module
except AttributeError: except AttributeError:
try: try:
self._urlconf_module = __import__(self.urlconf_name, '', '', ['']) self._urlconf_module = __import__(self.urlconf_name, {}, {}, [''])
except ValueError, e: except ValueError, e:
# Invalid urlconf_name, such as "foo.bar." (note trailing period) # Invalid urlconf_name, such as "foo.bar." (note trailing period)
raise ImproperlyConfigured, "Error while importing URLconf %r: %s" % (self.urlconf_name, e) raise ImproperlyConfigured, "Error while importing URLconf %r: %s" % (self.urlconf_name, e)
@ -175,7 +186,7 @@ class RegexURLResolver(object):
callback = getattr(self.urlconf_module, 'handler%s' % view_type) callback = getattr(self.urlconf_module, 'handler%s' % view_type)
mod_name, func_name = get_mod_func(callback) mod_name, func_name = get_mod_func(callback)
try: try:
return getattr(__import__(mod_name, '', '', ['']), func_name), {} return getattr(__import__(mod_name, {}, {}, ['']), func_name), {}
except (ImportError, AttributeError), e: except (ImportError, AttributeError), e:
raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e)) raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e))
@ -185,22 +196,28 @@ class RegexURLResolver(object):
def resolve500(self): def resolve500(self):
return self._resolve_special('500') return self._resolve_special('500')
def reverse(self, viewname, *args, **kwargs): def reverse(self, lookup_view, *args, **kwargs):
if not callable(lookup_view):
mod_name, func_name = get_mod_func(lookup_view)
try:
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError):
raise NoReverseMatch
for pattern in self.urlconf_module.urlpatterns: for pattern in self.urlconf_module.urlpatterns:
if isinstance(pattern, RegexURLResolver): if isinstance(pattern, RegexURLResolver):
try: try:
return pattern.reverse_helper(viewname, *args, **kwargs) return pattern.reverse_helper(lookup_view, *args, **kwargs)
except NoReverseMatch: except NoReverseMatch:
continue continue
elif pattern.callback == viewname: elif pattern.callback == lookup_view:
try: try:
return pattern.reverse_helper(*args, **kwargs) return pattern.reverse_helper(*args, **kwargs)
except NoReverseMatch: except NoReverseMatch:
continue continue
raise NoReverseMatch raise NoReverseMatch
def reverse_helper(self, viewname, *args, **kwargs): def reverse_helper(self, lookup_view, *args, **kwargs):
sub_match = self.reverse(viewname, *args, **kwargs) sub_match = self.reverse(lookup_view, *args, **kwargs)
result = reverse_helper(self.regex, *args, **kwargs) result = reverse_helper(self.regex, *args, **kwargs)
return result + sub_match return result + sub_match

View File

@ -13,7 +13,7 @@ from django.utils.translation import gettext, gettext_lazy, ngettext
from django.utils.functional import Promise, lazy from django.utils.functional import Promise, lazy
import re import re
_datere = r'(19|2\d)\d{2}-((?:0?[1-9])|(?:1[0-2]))-((?:0?[1-9])|(?:[12][0-9])|(?:3[0-1]))' _datere = r'\d{4}-\d{1,2}-\d{1,2}'
_timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?' _timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?'
alnum_re = re.compile(r'^\w+$') alnum_re = re.compile(r'^\w+$')
alnumurl_re = re.compile(r'^[-\w/]+$') alnumurl_re = re.compile(r'^[-\w/]+$')
@ -68,7 +68,7 @@ def isAlphaNumericURL(field_data, all_data):
def isSlug(field_data, all_data): def isSlug(field_data, all_data):
if not slug_re.search(field_data): if not slug_re.search(field_data):
raise ValidationError, "This value must contain only letters, numbers, underscores or hyphens." raise ValidationError, gettext("This value must contain only letters, numbers, underscores or hyphens.")
def isLowerCase(field_data, all_data): def isLowerCase(field_data, all_data):
if field_data.lower() != field_data: if field_data.lower() != field_data:
@ -122,9 +122,29 @@ def isOnlyLetters(field_data, all_data):
if not field_data.isalpha(): if not field_data.isalpha():
raise ValidationError, gettext("Only alphabetical characters are allowed here.") raise ValidationError, gettext("Only alphabetical characters are allowed here.")
def _isValidDate(date_string):
"""
A helper function used by isValidANSIDate and isValidANSIDatetime to
check if the date is valid. The date string is assumed to already be in
YYYY-MM-DD format.
"""
from datetime import date
# Could use time.strptime here and catch errors, but datetime.date below
# produces much friendlier error messages.
year, month, day = map(int, date_string.split('-'))
# This check is needed because strftime is used when saving the date
# value to the database, and strftime requires that the year be >=1900.
if year < 1900:
raise ValidationError, gettext('Year must be 1900 or later.')
try:
date(year, month, day)
except ValueError, e:
raise ValidationError, gettext('Invalid date: %s.' % e)
def isValidANSIDate(field_data, all_data): def isValidANSIDate(field_data, all_data):
if not ansi_date_re.search(field_data): if not ansi_date_re.search(field_data):
raise ValidationError, gettext('Enter a valid date in YYYY-MM-DD format.') raise ValidationError, gettext('Enter a valid date in YYYY-MM-DD format.')
_isValidDate(field_data)
def isValidANSITime(field_data, all_data): def isValidANSITime(field_data, all_data):
if not ansi_time_re.search(field_data): if not ansi_time_re.search(field_data):
@ -133,6 +153,7 @@ def isValidANSITime(field_data, all_data):
def isValidANSIDatetime(field_data, all_data): def isValidANSIDatetime(field_data, all_data):
if not ansi_datetime_re.search(field_data): if not ansi_datetime_re.search(field_data):
raise ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.') raise ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.')
_isValidDate(field_data.split()[0])
def isValidEmail(field_data, all_data): def isValidEmail(field_data, all_data):
if not email_re.search(field_data): if not email_re.search(field_data):
@ -227,9 +248,8 @@ def hasNoProfanities(field_data, all_data):
catch 'motherfucker' as well. Raises a ValidationError such as: catch 'motherfucker' as well. Raises a ValidationError such as:
Watch your mouth! The words "f--k" and "s--t" are not allowed here. Watch your mouth! The words "f--k" and "s--t" are not allowed here.
""" """
bad_words = ['asshat', 'asshead', 'asshole', 'cunt', 'fuck', 'gook', 'nigger', 'shit'] # all in lower case
field_data = field_data.lower() # normalize field_data = field_data.lower() # normalize
words_seen = [w for w in bad_words if field_data.find(w) > -1] words_seen = [w for w in settings.PROFANITIES_LIST if w in field_data]
if words_seen: if words_seen:
from django.utils.text import get_text_list from django.utils.text import get_text_list
plural = len(words_seen) > 1 plural = len(words_seen) > 1
@ -352,10 +372,12 @@ class IsValidFloat(object):
float(data) float(data)
except ValueError: except ValueError:
raise ValidationError, gettext("Please enter a valid decimal number.") raise ValidationError, gettext("Please enter a valid decimal number.")
if len(data) > (self.max_digits + 1): # Negative floats require more space to input.
max_allowed_length = data.startswith('-') and (self.max_digits + 2) or (self.max_digits + 1)
if len(data) > max_allowed_length:
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.", raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.",
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits "Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
if (not '.' in data and len(data) > (self.max_digits - self.decimal_places)) or ('.' in data and len(data) > (self.max_digits - (self.decimal_places - len(data.split('.')[1])) + 1)): if (not '.' in data and len(data) > (max_allowed_length - self.decimal_places - 1)) or ('.' in data and len(data) > (max_allowed_length - (self.decimal_places - len(data.split('.')[1])))):
raise ValidationError, ngettext( "Please enter a valid decimal number with a whole part of at most %s digit.", raise ValidationError, ngettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
"Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places) "Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
if '.' in data and len(data.split('.')[1]) > self.decimal_places: if '.' in data and len(data.split('.')[1]) > self.decimal_places:

View File

@ -13,9 +13,10 @@ def populate_xheaders(request, response, model, object_id):
""" """
Adds the "X-Object-Type" and "X-Object-Id" headers to the given Adds the "X-Object-Type" and "X-Object-Id" headers to the given
HttpResponse according to the given model and object_id -- but only if the HttpResponse according to the given model and object_id -- but only if the
given HttpRequest object has an IP address within the INTERNAL_IPS setting. given HttpRequest object has an IP address within the INTERNAL_IPS setting
or if the request is from a logged in staff member.
""" """
from django.conf import settings from django.conf import settings
if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS: if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS or (request.user.is_authenticated() and request.user.is_staff):
response['X-Object-Type'] = "%s.%s" % (model._meta.app_label, model._meta.object_name.lower()) response['X-Object-Type'] = "%s.%s" % (model._meta.app_label, model._meta.object_name.lower())
response['X-Object-Id'] = str(object_id) response['X-Object-Id'] = str(object_id)

View File

@ -8,7 +8,7 @@ if not settings.DATABASE_ENGINE:
settings.DATABASE_ENGINE = 'dummy' settings.DATABASE_ENGINE = 'dummy'
try: try:
backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, '', '', ['']) backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, {}, {}, [''])
except ImportError, e: except ImportError, e:
# The database backend wasn't found. Display a helpful error message # The database backend wasn't found. Display a helpful error message
# listing all possible database backends. # listing all possible database backends.
@ -23,9 +23,9 @@ except ImportError, e:
else: else:
raise # If there's some other error, this must be an error in Django itself. raise # If there's some other error, this must be an error in Django itself.
get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, '', '', ['']) get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, [''])
get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, '', '', ['']) get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, [''])
runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, '', '', ['']).runshell() runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell()
connection = backend.DatabaseWrapper() connection = backend.DatabaseWrapper()
DatabaseError = backend.DatabaseError DatabaseError = backend.DatabaseError

View File

@ -13,6 +13,7 @@ except ImportError, e:
from MySQLdb.converters import conversions from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE from MySQLdb.constants import FIELD_TYPE
import types import types
import re
DatabaseError = Database.DatabaseError DatabaseError = Database.DatabaseError
@ -24,6 +25,12 @@ django_conversions.update({
FIELD_TYPE.TIME: util.typecast_time, FIELD_TYPE.TIME: util.typecast_time,
}) })
# This should match the numerical portion of the version numbers (we can treat
# versions like 5.0.24 and 5.0.24a as the same). Based on the list of version
# at http://dev.mysql.com/doc/refman/4.1/en/news.html and
# http://dev.mysql.com/doc/refman/5.0/en/news.html .
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
# This is an extra debug layer over MySQL queries, to display warnings. # This is an extra debug layer over MySQL queries, to display warnings.
# It's only used when DEBUG=True. # It's only used when DEBUG=True.
class MysqlDebugWrapper: class MysqlDebugWrapper:
@ -61,6 +68,7 @@ class DatabaseWrapper(local):
def __init__(self): def __init__(self):
self.connection = None self.connection = None
self.queries = [] self.queries = []
self.server_version = None
def _valid_connection(self): def _valid_connection(self):
if self.connection is not None: if self.connection is not None:
@ -110,6 +118,16 @@ class DatabaseWrapper(local):
self.connection.close() self.connection.close()
self.connection = None self.connection = None
def get_server_version(self):
if not self.server_version:
if not self._valid_connection():
self.cursor()
m = server_version_re.match(self.connection.get_server_info())
if not m:
raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
self.server_version = tuple([int(x) for x in m.groups()])
return self.server_version
supports_constraints = True supports_constraints = True
def quote_name(name): def quote_name(name):

View File

@ -36,13 +36,14 @@ def get_relations(cursor, table_name):
SELECT column_name, referenced_table_name, referenced_column_name SELECT column_name, referenced_table_name, referenced_column_name
FROM information_schema.key_column_usage FROM information_schema.key_column_usage
WHERE table_name = %s WHERE table_name = %s
AND table_schema = DATABASE()
AND referenced_table_name IS NOT NULL AND referenced_table_name IS NOT NULL
AND referenced_column_name IS NOT NULL""", [table_name]) AND referenced_column_name IS NOT NULL""", [table_name])
constraints.extend(cursor.fetchall()) constraints.extend(cursor.fetchall())
except (ProgrammingError, OperationalError): except (ProgrammingError, OperationalError):
# Fall back to "SHOW CREATE TABLE", for previous MySQL versions. # Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
# Go through all constraints and save the equal matches. # Go through all constraints and save the equal matches.
cursor.execute("SHOW CREATE TABLE %s" % table_name) cursor.execute("SHOW CREATE TABLE %s" % quote_name(table_name))
for row in cursor.fetchall(): for row in cursor.fetchall():
pos = 0 pos = 0
while True: while True:

View File

@ -43,6 +43,7 @@ class DatabaseWrapper(local):
self.connection = Database.connect(conn_string) self.connection = Database.connect(conn_string)
self.connection.set_isolation_level(1) # make transactions transparent to all cursors self.connection.set_isolation_level(1) # make transactions transparent to all cursors
cursor = self.connection.cursor() cursor = self.connection.cursor()
cursor.tzinfo_factory = None
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE]) cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
if settings.DEBUG: if settings.DEBUG:
return util.CursorDebugWrapper(cursor, self) return util.CursorDebugWrapper(cursor, self)
@ -67,23 +68,9 @@ def quote_name(name):
return name # Quoting once is enough. return name # Quoting once is enough.
return '"%s"' % name return '"%s"' % name
def dictfetchone(cursor): dictfetchone = util.dictfetchone
"Returns a row from the cursor as a dict" dictfetchmany = util.dictfetchmany
# TODO: cursor.dictfetchone() doesn't exist in psycopg2, dictfetchall = util.dictfetchall
# but no Django code uses this. Safe to remove?
return cursor.dictfetchone()
def dictfetchmany(cursor, number):
"Returns a certain number of rows from a cursor as a dict"
# TODO: cursor.dictfetchmany() doesn't exist in psycopg2,
# but no Django code uses this. Safe to remove?
return cursor.dictfetchmany(number)
def dictfetchall(cursor):
"Returns all rows from a cursor as a dict"
# TODO: cursor.dictfetchall() doesn't exist in psycopg2,
# but no Django code uses this. Safe to remove?
return cursor.dictfetchall()
def get_last_insert_id(cursor, table_name, pk_name): def get_last_insert_id(cursor, table_name, pk_name):
cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name)) cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))

View File

@ -4,10 +4,18 @@ SQLite3 backend for django. Requires pysqlite2 (http://pysqlite.org/).
from django.db.backends import util from django.db.backends import util
try: try:
try:
from sqlite3 import dbapi2 as Database
except ImportError:
from pysqlite2 import dbapi2 as Database from pysqlite2 import dbapi2 as Database
except ImportError, e: except ImportError, e:
import sys
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured, "Error loading pysqlite2 module: %s" % e if sys.version_info < (2, 5, 0):
module = 'pysqlite2'
else:
module = 'sqlite3'
raise ImproperlyConfigured, "Error loading %s module: %s" % (module, e)
DatabaseError = Database.DatabaseError DatabaseError = Database.DatabaseError
@ -62,7 +70,10 @@ class DatabaseWrapper(local):
self.connection.rollback() self.connection.rollback()
def close(self): def close(self):
if self.connection is not None: from django.conf import settings
# If database is in memory, closing the connection destroys the database.
# To prevent accidental data loss, ignore close requests on an in-memory db.
if self.connection is not None and settings.DATABASE_NAME != ":memory:":
self.connection.close() self.connection.close()
self.connection = None self.connection = None

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