1
0
mirror of https://github.com/django/django.git synced 2025-07-06 18:59:13 +00:00

queryset-refactor: Merged changes from trunk up to [7085].

git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7086 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-02-04 05:45:17 +00:00
parent a4343209db
commit 0a9b751958
57 changed files with 18250 additions and 10737 deletions

View File

@ -45,6 +45,8 @@ answer newbie questions, and generally made Django that much better:
Marty Alchin <gulopine@gamemusic.org> Marty Alchin <gulopine@gamemusic.org>
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com> Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
AgarFu <heaven@croasanaso.sytes.net> AgarFu <heaven@croasanaso.sytes.net>
Dagur Páll Ammendrup <dagurp@gmail.com>
Collin Anderson <cmawebsite@gmail.com>
Andreas Andreas
andy@jadedplanet.net andy@jadedplanet.net
Fabrice Aneche <akh@nobugware.com> Fabrice Aneche <akh@nobugware.com>
@ -52,7 +54,7 @@ answer newbie questions, and generally made Django that much better:
Florian Apolloner Florian Apolloner
arien <regexbot@gmail.com> arien <regexbot@gmail.com>
David Ascher <http://ascher.ca/> David Ascher <http://ascher.ca/>
david@kazserve.org Jökull Sólberg Auðunsson <jokullsolberg@gmail.com>
Arthur <avandorp@gmail.com> Arthur <avandorp@gmail.com>
axiak@mit.edu axiak@mit.edu
Jiri Barton Jiri Barton
@ -99,6 +101,7 @@ answer newbie questions, and generally made Django that much better:
Dirk Datzert <dummy@habmalnefrage.de> Dirk Datzert <dummy@habmalnefrage.de>
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/> Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
dave@thebarproject.com dave@thebarproject.com
david@kazserve.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
@ -228,7 +231,7 @@ answer newbie questions, and generally made Django that much better:
mccutchen@gmail.com mccutchen@gmail.com
michael.mcewan@gmail.com michael.mcewan@gmail.com
michal@plovarna.cz michal@plovarna.cz
mikko@sorl.net Mikko Hellsing <mikko@sorl.net>
Slawek Mikula <slawek dot mikula at gmail dot com> Slawek Mikula <slawek dot mikula at gmail dot com>
mitakummaa@gmail.com mitakummaa@gmail.com
mmarshall mmarshall
@ -301,6 +304,7 @@ answer newbie questions, and generally made Django that much better:
Don Spaulding <donspauldingii@gmail.com> Don Spaulding <donspauldingii@gmail.com>
Bjørn Stabell <bjorn@exoweb.net> Bjørn Stabell <bjorn@exoweb.net>
Georgi Stanojevski <glisha@gmail.com> Georgi Stanojevski <glisha@gmail.com>
starrynight <cmorgh@gmail.com>
Vasiliy Stavenko <stavenko@gmail.com> Vasiliy Stavenko <stavenko@gmail.com>
Thomas Steinacher <http://www.eggdrop.ch/> Thomas Steinacher <http://www.eggdrop.ch/>
Johan C. Stöver <johan@nilling.nl> Johan C. Stöver <johan@nilling.nl>

File diff suppressed because it is too large Load Diff

View File

@ -9,14 +9,14 @@ msgstr ""
"Project-Id-Version: djangojs\n" "Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-05-20 18:25+0200\n" "POT-Creation-Date: 2007-05-20 18:25+0200\n"
"PO-Revision-Date: 2007-12-01 12:06+0100\n" "PO-Revision-Date: 2008-01-22 19:39+0100\n"
"Last-Translator: Antoni Aloy <antoni.aloy@trespams.com>\n" "Last-Translator: Marc Garcia <marc.garcia@accopensys.com>\n"
"Language-Team: español <ca@li.org>\n" "Language-Team: español <ca@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"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n" "X-Generator: KBabel 1.11.4\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: contrib/admin/media/js/SelectFilter2.js:33 #: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format #, perl-format
@ -50,9 +50,7 @@ msgstr "Deseleccionar tots"
#: 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 "Gener Febrer Març Abril Maig Juny Juliol Agost Setembre Octubre Novembre Desembre" msgstr "Gener Febrer Març Abril Maig Juny Juliol Agost Setembre Octubre Novembre Desembre"
#: contrib/admin/media/js/dateparse.js:33 #: contrib/admin/media/js/dateparse.js:33
@ -61,7 +59,7 @@ msgstr "Diumenge Dilluns Dimarts Dimecres Dijous Divendres Dissabte"
#: 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 "D L M X J V S" msgstr "Dg Dl Dt Dc Dj Dv Ds"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:81

View File

@ -2614,6 +2614,34 @@ msgstr "Samstag"
msgid "Sunday" msgid "Sunday"
msgstr "Sonntag" msgstr "Sonntag"
#: utils/dates.py:10
msgid "Mon"
msgstr "Mo"
#: utils/dates.py:10
msgid "Tue"
msgstr "Di"
#: utils/dates.py:10
msgid "Wed"
msgstr "Mi"
#: utils/dates.py:10
msgid "Thu"
msgstr "Do"
#: utils/dates.py:10
msgid "Fri"
msgstr "Fr"
#: utils/dates.py:11
msgid "Sat"
msgstr "Sa"
#: utils/dates.py:11
msgid "Sun"
msgstr "So"
#: utils/dates.py:14 #: utils/dates.py:14
msgid "January" msgid "January"
msgstr "Januar" msgstr "Januar"

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

View File

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: django 1.0\n" "Project-Id-Version: django 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-09-14 12:33+0100\n" "POT-Creation-Date: 2007-09-14 12:33+0100\n"
"PO-Revision-Date: 2007-09-14 14:19+0100\n" "PO-Revision-Date: 2008-01-23 11:04+0100\n"
"Last-Translator: Michael Thornhill <michael.thornhill@gmail.com>\n" "Last-Translator: Michael Thornhill <michael@maithu.com>\n"
"Language-Team: Gaeilge <ga@li.org>\n" "Language-Team: Gaeilge <ga@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"
@ -18,99 +18,99 @@ msgstr ""
#: contrib/admin/media/js/calendar.js:24 #: contrib/admin/media/js/calendar.js:24
#: contrib/admin/media/js/dateparse.js:32 #: contrib/admin/media/js/dateparse.js:32
msgid "January February March April May June July August September October November December" msgid "January February March April May June July August September October November December"
msgstr "" msgstr "Eanair Feabhra Márta Aibreán Bealtaine Meitheamh Iúil Lúnasa Mean Fómhair Deireadh Fómhair Nollaig"
#: 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 "D L M C D A S"
#: 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 "Domhnaigh Luain Máirt Céadaoin Déardaoin Aoine Sathairn"
#: contrib/admin/media/js/SelectFilter2.js:33 #: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format #, perl-format
msgid "Available %s" msgid "Available %s"
msgstr "" msgstr "%s ar fáil"
#: contrib/admin/media/js/SelectFilter2.js:41 #: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all" msgid "Choose all"
msgstr "" msgstr "Roghnaigh iomlán"
#: contrib/admin/media/js/SelectFilter2.js:46 #: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add" msgid "Add"
msgstr "" msgstr "Cuir le"
#: contrib/admin/media/js/SelectFilter2.js:48 #: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove" msgid "Remove"
msgstr "" msgstr "Bain amach"
#: contrib/admin/media/js/SelectFilter2.js:53 #: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format #, perl-format
msgid "Chosen %s" msgid "Chosen %s"
msgstr "" msgstr "Roghnófar %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 "Roghnaigh do rogha agus cniog"
#: contrib/admin/media/js/SelectFilter2.js:59 #: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all" msgid "Clear all"
msgstr "" msgstr "Glan iomlán"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now" msgid "Now"
msgstr "" msgstr "Anois"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock" msgid "Clock"
msgstr "" msgstr "Clog"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time" msgid "Choose a time"
msgstr "" msgstr "Roghnaigh am"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight" msgid "Midnight"
msgstr "" msgstr "Meán oíche"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m." msgid "6 a.m."
msgstr "" msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon" msgid "Noon"
msgstr "" msgstr "Nóin"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr "Cealaigh"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today" msgid "Today"
msgstr "" msgstr "Inniu"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar" msgid "Calendar"
msgstr "" msgstr "Féilire"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday" msgid "Yesterday"
msgstr "" msgstr "Inné"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow" msgid "Tomorrow"
msgstr "" msgstr "Amárach"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show" msgid "Show"
msgstr "" msgstr "Taispeán"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide" msgid "Hide"
msgstr "" msgstr "Folaigh"

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

View File

@ -6,8 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: djangojs\n" "Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-03-06 02:29+0100\n" "POT-Creation-Date: 2008-02-01 15:31+0100\n"
"PO-Revision-Date: 2007-03-06 10:30+0100\n" "PO-Revision-Date: 2008-02-01 15:32+0100\n"
"Last-Translator: Mikko Hellsing <mikko@sorl.net>\n" "Last-Translator: Mikko Hellsing <mikko@sorl.net>\n"
"Language-Team: Django I18N <Django-I18N@googlegroups.com>\n" "Language-Team: Django I18N <Django-I18N@googlegroups.com>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -20,7 +20,7 @@ msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:33 #: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format #, perl-format
msgid "Available %s" msgid "Available %s"
msgstr "Tillgänglig %s" msgstr "Tillgängliga %s"
#: contrib/admin/media/js/SelectFilter2.js:41 #: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all" msgid "Choose all"
@ -37,7 +37,7 @@ msgstr "Ta bort"
#: contrib/admin/media/js/SelectFilter2.js:53 #: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format #, perl-format
msgid "Chosen %s" msgid "Chosen %s"
msgstr "Vald %s" msgstr "Valda %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 "
@ -47,8 +47,8 @@ msgstr "Gör dina val och klicka på "
msgid "Clear all" msgid "Clear all"
msgstr "Ta bort alla" msgstr "Ta bort alla"
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24 #: contrib/admin/media/js/calendar.js:24
#: contrib/admin/media/js/dateparse.js:32
msgid "" 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"
@ -56,14 +56,14 @@ msgstr ""
"Januari Februari Mars April Maj Juni Juli Augusti September Oktober November " "Januari Februari Mars April Maj Juni Juli Augusti September Oktober November "
"December" "December"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Söndag Måndag Tisdag Onsdag Torsdag Fredag Lördag"
#: 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 "S M T O T F L" msgstr "S M T O T F L"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Söndag Måndag Tisdag Onsdag Torsdag Fredag Lördag"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show" msgid "Show"
@ -118,5 +118,4 @@ msgstr "Igår"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow" msgid "Tomorrow"
msgstr "I morgon" msgstr "Imorgon"

View File

@ -18,7 +18,7 @@ DATABASE_PORT = '' # Set to empty string for default. Not used with
# Local time zone for this installation. Choices can be found here: # Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be avilable on all operating systems. # although not all choices may be available on all operating systems.
# If running in a Windows environment this must be set to the same as your # If running in a Windows environment this must be set to the same as your
# system time zone. # system time zone.
TIME_ZONE = 'America/Chicago' TIME_ZONE = 'America/Chicago'

View File

@ -1,5 +1,5 @@
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
urlpatterns = patterns('django.views', urlpatterns = patterns('django.views',
(r'^(?P<content_type_id>\d+)/(?P<object_id>\d+)/$', 'defaults.shortcut'), (r'^(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'defaults.shortcut'),
) )

View File

@ -34,7 +34,7 @@
{% for bound_field_set in bound_field_sets %} {% for bound_field_set in bound_field_sets %}
<fieldset class="module aligned {{ bound_field_set.classes }}"> <fieldset class="module aligned {{ bound_field_set.classes }}">
{% if bound_field_set.name %}<h2>{{ bound_field_set.name }}</h2>{% endif %} {% if bound_field_set.name %}<h2>{{ bound_field_set.name }}</h2>{% endif %}
{% if bound_field_set.description %}<div class="description">{{ bound_field_set.description }}</div>{% endif %} {% if bound_field_set.description %}<div class="description">{{ bound_field_set.description|safe }}</div>{% endif %}
{% for bound_field_line in bound_field_set %} {% for bound_field_line in bound_field_set %}
{% admin_field_line bound_field_line %} {% admin_field_line bound_field_line %}
{% for bound_field in bound_field_line %} {% for bound_field in bound_field_line %}

View File

@ -8,7 +8,7 @@ else:
urlpatterns = patterns('', urlpatterns = patterns('',
('^$', 'django.contrib.admin.views.main.index'), ('^$', 'django.contrib.admin.views.main.index'),
('^r/(\d+)/(.*)/$', 'django.views.defaults.shortcut'), ('^r/', include('django.conf.urls.shortcut')),
('^jsi18n/$', i18n_view, {'packages': 'django.conf'}), ('^jsi18n/$', i18n_view, {'packages': 'django.conf'}),
('^logout/$', 'django.contrib.auth.views.logout'), ('^logout/$', 'django.contrib.auth.views.logout'),
('^password_change/$', 'django.contrib.auth.views.password_change'), ('^password_change/$', 'django.contrib.auth.views.password_change'),

View File

@ -1,25 +1,27 @@
import datetime
from django.db import models from django.db import models
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
import datetime
MIN_PHOTO_DIMENSION = 5 MIN_PHOTO_DIMENSION = 5
MAX_PHOTO_DIMENSION = 1000 MAX_PHOTO_DIMENSION = 1000
# option codes for comment-form hidden fields # Option codes for comment-form hidden fields.
PHOTOS_REQUIRED = 'pr' PHOTOS_REQUIRED = 'pr'
PHOTOS_OPTIONAL = 'pa' PHOTOS_OPTIONAL = 'pa'
RATINGS_REQUIRED = 'rr' RATINGS_REQUIRED = 'rr'
RATINGS_OPTIONAL = 'ra' RATINGS_OPTIONAL = 'ra'
IS_PUBLIC = 'ip' IS_PUBLIC = 'ip'
# what users get if they don't have any karma # What users get if they don't have any karma.
DEFAULT_KARMA = 5 DEFAULT_KARMA = 5
KARMA_NEEDED_BEFORE_DISPLAYED = 3 KARMA_NEEDED_BEFORE_DISPLAYED = 3
class CommentManager(models.Manager): class CommentManager(models.Manager):
def get_security_hash(self, options, photo_options, rating_options, target): def get_security_hash(self, options, photo_options, rating_options, target):
""" """
@ -61,7 +63,9 @@ class CommentManager(models.Manager):
return True return True
return False return False
class Comment(models.Model): class Comment(models.Model):
"""A comment by a registered user."""
user = models.ForeignKey(User, raw_id_admin=True) user = models.ForeignKey(User, raw_id_admin=True)
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID')) object_id = models.IntegerField(_('object ID'))
@ -86,10 +90,12 @@ class Comment(models.Model):
is_removed = models.BooleanField(_('is removed'), help_text=_('Check this box if the comment is inappropriate. A "This comment has been removed" message will be displayed instead.')) is_removed = models.BooleanField(_('is removed'), help_text=_('Check this box if the comment is inappropriate. A "This comment has been removed" message will be displayed instead.'))
site = models.ForeignKey(Site) site = models.ForeignKey(Site)
objects = CommentManager() objects = CommentManager()
class Meta: class Meta:
verbose_name = _('comment') verbose_name = _('comment')
verbose_name_plural = _('comments') verbose_name_plural = _('comments')
ordering = ('-submit_date',) ordering = ('-submit_date',)
class Admin: class Admin:
fields = ( fields = (
(None, {'fields': ('content_type', 'object_id', 'site')}), (None, {'fields': ('content_type', 'object_id', 'site')}),
@ -134,7 +140,7 @@ class Comment(models.Model):
get_content_object.short_description = _('Content object') get_content_object.short_description = _('Content object')
def _fill_karma_cache(self): def _fill_karma_cache(self):
"Helper function that populates good/bad karma caches" """Helper function that populates good/bad karma caches."""
good, bad = 0, 0 good, bad = 0, 0
for k in self.karmascore_set: for k in self.karmascore_set:
if k.score == -1: if k.score == -1:
@ -163,8 +169,9 @@ class Comment(models.Model):
{'user': self.user.username, 'date': self.submit_date, {'user': self.user.username, 'date': self.submit_date,
'comment': self.comment, 'domain': self.site.domain, 'url': self.get_absolute_url()} 'comment': self.comment, 'domain': self.site.domain, 'url': self.get_absolute_url()}
class FreeComment(models.Model): class FreeComment(models.Model):
# A FreeComment is a comment by a non-registered user. """A comment by a non-registered user."""
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID')) object_id = models.IntegerField(_('object ID'))
comment = models.TextField(_('comment'), max_length=3000) comment = models.TextField(_('comment'), max_length=3000)
@ -175,10 +182,12 @@ class FreeComment(models.Model):
# TODO: Change this to is_removed, like Comment # TODO: Change this to is_removed, like Comment
approved = models.BooleanField(_('approved by staff')) approved = models.BooleanField(_('approved by staff'))
site = models.ForeignKey(Site) site = models.ForeignKey(Site)
class Meta: class Meta:
verbose_name = _('free comment') verbose_name = _('free comment')
verbose_name_plural = _('free comments') verbose_name_plural = _('free comments')
ordering = ('-submit_date',) ordering = ('-submit_date',)
class Admin: class Admin:
fields = ( fields = (
(None, {'fields': ('content_type', 'object_id', 'site')}), (None, {'fields': ('content_type', 'object_id', 'site')}),
@ -212,6 +221,7 @@ class FreeComment(models.Model):
get_content_object.short_description = _('Content object') get_content_object.short_description = _('Content object')
class KarmaScoreManager(models.Manager): class KarmaScoreManager(models.Manager):
def vote(self, user_id, comment_id, score): def vote(self, user_id, comment_id, score):
try: try:
@ -233,12 +243,14 @@ class KarmaScoreManager(models.Manager):
return DEFAULT_KARMA return DEFAULT_KARMA
return int(round((4.5 * score) + 5.5)) return int(round((4.5 * score) + 5.5))
class KarmaScore(models.Model): class KarmaScore(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
comment = models.ForeignKey(Comment) comment = models.ForeignKey(Comment)
score = models.SmallIntegerField(_('score'), db_index=True) score = models.SmallIntegerField(_('score'), db_index=True)
scored_date = models.DateTimeField(_('score date'), auto_now=True) scored_date = models.DateTimeField(_('score date'), auto_now=True)
objects = KarmaScoreManager() objects = KarmaScoreManager()
class Meta: class Meta:
verbose_name = _('karma score') verbose_name = _('karma score')
verbose_name_plural = _('karma scores') verbose_name_plural = _('karma scores')
@ -247,6 +259,7 @@ class KarmaScore(models.Model):
def __unicode__(self): def __unicode__(self):
return _("%(score)d rating by %(user)s") % {'score': self.score, 'user': self.user} return _("%(score)d rating by %(user)s") % {'score': self.score, 'user': self.user}
class UserFlagManager(models.Manager): class UserFlagManager(models.Manager):
def flag(self, comment, user): def flag(self, comment, user):
""" """
@ -257,7 +270,7 @@ class UserFlagManager(models.Manager):
if int(comment.user_id) == int(user.id): if int(comment.user_id) == int(user.id):
return # A user can't flag his own comment. Fail silently. return # A user can't flag his own comment. Fail silently.
try: try:
f = self.objects.get(user__pk=user.id, comment__pk=comment.id) f = self.get(user__pk=user.id, comment__pk=comment.id)
except self.model.DoesNotExist: except self.model.DoesNotExist:
from django.core.mail import mail_managers from django.core.mail import mail_managers
f = self.model(None, user.id, comment.id, None) f = self.model(None, user.id, comment.id, None)
@ -265,11 +278,13 @@ class UserFlagManager(models.Manager):
mail_managers('Comment flagged', message, fail_silently=True) mail_managers('Comment flagged', message, fail_silently=True)
f.save() f.save()
class UserFlag(models.Model): class UserFlag(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
comment = models.ForeignKey(Comment) comment = models.ForeignKey(Comment)
flag_date = models.DateTimeField(_('flag date'), auto_now_add=True) flag_date = models.DateTimeField(_('flag date'), auto_now_add=True)
objects = UserFlagManager() objects = UserFlagManager()
class Meta: class Meta:
verbose_name = _('user flag') verbose_name = _('user flag')
verbose_name_plural = _('user flags') verbose_name_plural = _('user flags')
@ -278,10 +293,12 @@ class UserFlag(models.Model):
def __unicode__(self): def __unicode__(self):
return _("Flag by %r") % self.user return _("Flag by %r") % self.user
class ModeratorDeletion(models.Model): class ModeratorDeletion(models.Model):
user = models.ForeignKey(User, verbose_name='moderator') user = models.ForeignKey(User, verbose_name='moderator')
comment = models.ForeignKey(Comment) comment = models.ForeignKey(Comment)
deletion_date = models.DateTimeField(_('deletion date'), auto_now_add=True) deletion_date = models.DateTimeField(_('deletion date'), auto_now_add=True)
class Meta: class Meta:
verbose_name = _('moderator deletion') verbose_name = _('moderator deletion')
verbose_name_plural = _('moderator deletions') verbose_name_plural = _('moderator deletions')

View File

@ -105,7 +105,7 @@ class EasyInstance(object):
return self.instance._get_pk_val() return self.instance._get_pk_val()
def url(self): def url(self):
return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk())) return mark_safe('%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk())))
def fields(self): def fields(self):
""" """

View File

@ -20,7 +20,7 @@ class ARProvinceSelect(Select):
class ARPostalCodeField(RegexField): class ARPostalCodeField(RegexField):
""" """
A field that accepts a `classic´ NNNN Postal Code or a CPA. A field that accepts a 'classic' NNNN Postal Code or a CPA.
See http://www.correoargentino.com.ar/consulta_cpa/home.php See http://www.correoargentino.com.ar/consulta_cpa/home.php
""" """
@ -44,7 +44,7 @@ class ARPostalCodeField(RegexField):
class ARDNIField(CharField): class ARDNIField(CharField):
""" """
A field that validates `Documento Nacional de Identidad´ (DNI) numbers. A field that validates 'Documento Nacional de Identidad' (DNI) numbers.
""" """
default_error_messages = { default_error_messages = {
'invalid': ugettext("This field requires only numbers."), 'invalid': ugettext("This field requires only numbers."),
@ -73,7 +73,7 @@ class ARDNIField(CharField):
class ARCUITField(RegexField): class ARCUITField(RegexField):
""" """
This field validates a CUIT (Código Único de Identificación Tributaria). A This field validates a CUIT (Código Único de Identificación Tributaria). A
CUIT is of the form XX-XXXXXXXX-V. The last digit is a check digit. CUIT is of the form XX-XXXXXXXX-V. The last digit is a check digit.
""" """
default_error_messages = { default_error_messages = {

View File

@ -55,7 +55,7 @@ NORTHERN_IRELAND_REGION_CHOICES = (
("County Antrim", _("County Antrim")), ("County Antrim", _("County Antrim")),
("County Armagh", _("County Armagh")), ("County Armagh", _("County Armagh")),
("County Down", _("County Down")), ("County Down", _("County Down")),
("County Fermanagh", _("County Down")), ("County Fermanagh", _("County Fermanagh")),
("County Londonderry", _("County Londonderry")), ("County Londonderry", _("County Londonderry")),
("County Tyrone", _("County Tyrone")), ("County Tyrone", _("County Tyrone")),
) )

View File

@ -6,7 +6,7 @@ from django.utils.encoding import smart_unicode, iri_to_uri
from django.conf import settings from django.conf import settings
def add_domain(domain, url): def add_domain(domain, url):
if not url.startswith('http://'): if not (url.startswith('http://') or url.startswith('https://')):
# 'url' must already be ASCII and URL-quoted, so no need for encoding # 'url' must already be ASCII and URL-quoted, so no need for encoding
# conversions here. # conversions here.
url = iri_to_uri(u'http://%s%s' % (domain, url)) url = iri_to_uri(u'http://%s%s' % (domain, url))
@ -82,7 +82,8 @@ class Feed(object):
link = link, link = link,
description = self.__get_dynamic_attr('description', obj), description = self.__get_dynamic_attr('description', obj),
language = settings.LANGUAGE_CODE.decode(), language = settings.LANGUAGE_CODE.decode(),
feed_url = add_domain(current_site, self.__get_dynamic_attr('feed_url', obj)), feed_url = add_domain(current_site.domain,
self.__get_dynamic_attr('feed_url', obj)),
author_name = self.__get_dynamic_attr('author_name', obj), author_name = self.__get_dynamic_attr('author_name', obj),
author_link = self.__get_dynamic_attr('author_link', obj), author_link = self.__get_dynamic_attr('author_link', obj),
author_email = self.__get_dynamic_attr('author_email', obj), author_email = self.__get_dynamic_attr('author_email', obj),

View File

@ -111,13 +111,13 @@ class BaseHandler(object):
except SystemExit: except SystemExit:
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.
# Get the exception info now, in case another exception is thrown later.
exc_info = sys.exc_info()
receivers = dispatcher.send(signal=signals.got_request_exception, request=request)
if settings.DEBUG: if settings.DEBUG:
from django.views import debug from django.views import debug
return debug.technical_500_response(request, *sys.exc_info()) return debug.technical_500_response(request, *exc_info)
else: else:
# Get the exception info now, in case another exception is thrown later.
exc_info = sys.exc_info()
receivers = dispatcher.send(signal=signals.got_request_exception, request=request)
# 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'), request.path) subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
try: try:

View File

@ -59,7 +59,7 @@ class Command(BaseCommand):
else: else:
formats = [] formats = []
if verbosity > 2: if verbosity >= 2:
if formats: if formats:
print "Loading '%s' fixtures..." % fixture_name print "Loading '%s' fixtures..." % fixture_name
else: else:
@ -109,7 +109,7 @@ class Command(BaseCommand):
return return
fixture.close() fixture.close()
except: except:
if verbosity > 2: if verbosity >= 2:
print "No %s fixture '%s' in %s." % \ print "No %s fixture '%s' in %s." % \
(format, fixture_name, humanize(fixture_dir)) (format, fixture_name, humanize(fixture_dir))
@ -125,7 +125,7 @@ class Command(BaseCommand):
transaction.leave_transaction_management() transaction.leave_transaction_management()
if count[0] == 0: if count[0] == 0:
if verbosity > 2: if verbosity >= 2:
print "No fixtures found." print "No fixtures found."
else: else:
if verbosity > 0: if verbosity > 0:

View File

@ -209,7 +209,8 @@ class Model(object):
_prepare = classmethod(_prepare) _prepare = classmethod(_prepare)
def save(self, raw=False): def save(self, raw=False):
dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self) dispatcher.send(signal=signals.pre_save, sender=self.__class__,
instance=self, raw=raw)
non_pks = [f for f in self._meta.fields if not f.primary_key] non_pks = [f for f in self._meta.fields if not f.primary_key]
@ -255,7 +256,7 @@ class Model(object):
# Run any post-save hooks. # Run any post-save hooks.
dispatcher.send(signal=signals.post_save, sender=self.__class__, dispatcher.send(signal=signals.post_save, sender=self.__class__,
instance=self, created=(not record_exists)) instance=self, created=(not record_exists), raw=raw)
save.alters_data = True save.alters_data = True

View File

@ -22,12 +22,12 @@ class GZipMiddleware(object):
if response.has_header('Content-Encoding'): if response.has_header('Content-Encoding'):
return response return response
# Older versions of IE have issues with gzipped javascript. # Older versions of IE have issues with gzipped pages containing either
# See http://code.djangoproject.com/ticket/2449 # Javascript and PDF.
is_ie = "msie" in request.META.get('HTTP_USER_AGENT', '').lower() if "msie" in request.META.get('HTTP_USER_AGENT', '').lower():
is_js = "javascript" in response.get('Content-Type', '').lower() ctype = response.get('Content-Type', '').lower()
if is_ie and is_js: if "javascript" in ctype or ctype == "application/pdf":
return response return response
ae = request.META.get('HTTP_ACCEPT_ENCODING', '') ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
if not re_accepts_gzip.search(ae): if not re_accepts_gzip.search(ae):

View File

@ -228,7 +228,7 @@ class ModelFormMetaclass(type):
opts = ModelFormOptions(attrs.get('Meta', None)) opts = ModelFormOptions(attrs.get('Meta', None))
attrs['_meta'] = opts attrs['_meta'] = opts
# Don't allow more than one Meta model defenition in bases. The fields # Don't allow more than one Meta model definition in bases. The fields
# would be generated correctly, but the save method won't deal with # would be generated correctly, but the save method won't deal with
# more than one object. # more than one object.
base_models = [] base_models = []

View File

@ -426,7 +426,7 @@ class MultiWidget(Widget):
if id_: if id_:
final_attrs = dict(final_attrs, id='%s_%s' % (id_, i)) final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
output.append(widget.render(name + '_%s' % i, widget_value, final_attrs)) output.append(widget.render(name + '_%s' % i, widget_value, final_attrs))
return self.format_output(output) return mark_safe(self.format_output(output))
def id_for_label(self, id_): def id_for_label(self, id_):
# See the comment for RadioSelect.id_for_label() # See the comment for RadioSelect.id_for_label()

View File

@ -289,6 +289,9 @@ class Parser(object):
return NodeList() return NodeList()
def extend_nodelist(self, nodelist, node, token): def extend_nodelist(self, nodelist, node, token):
if (node.must_be_first and nodelist and
(not isinstance(nodelist[0], TextNode) or len(nodelist) > 2)):
raise TemplateSyntaxError("%r must be the first tag in the template." % node)
nodelist.append(node) nodelist.append(node)
def enter_command(self, command, token): def enter_command(self, command, token):
@ -708,6 +711,10 @@ class Variable(object):
return current return current
class Node(object): class Node(object):
# Set this to True for nodes that must be first in the template (although
# they can be preceded by text nodes.
must_be_first = False
def render(self, context): def render(self, context):
"Return the node rendered as a string" "Return the node rendered as a string"
pass pass

View File

@ -343,7 +343,7 @@ def force_escape(value):
""" """
from django.utils.html import escape from django.utils.html import escape
return mark_safe(escape(value)) return mark_safe(escape(value))
escape = stringfilter(escape) force_escape = stringfilter(force_escape)
force_escape.is_safe = True force_escape.is_safe = True
def linebreaks(value, autoescape=None): def linebreaks(value, autoescape=None):

View File

@ -1,5 +1,5 @@
from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable
from django.template import Library, Node from django.template import Library, Node, TextNode
from django.template.loader import get_template, get_template_from_string, find_template_source from django.template.loader import get_template, get_template_from_string, find_template_source
from django.conf import settings from django.conf import settings
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -37,11 +37,18 @@ class BlockNode(Node):
self.parent = BlockNode(self.name, nodelist) self.parent = BlockNode(self.name, nodelist)
class ExtendsNode(Node): class ExtendsNode(Node):
must_be_first = True
def __init__(self, nodelist, parent_name, parent_name_expr, template_dirs=None): def __init__(self, nodelist, parent_name, parent_name_expr, template_dirs=None):
self.nodelist = nodelist self.nodelist = nodelist
self.parent_name, self.parent_name_expr = parent_name, parent_name_expr self.parent_name, self.parent_name_expr = parent_name, parent_name_expr
self.template_dirs = template_dirs self.template_dirs = template_dirs
def __repr__(self):
if self.parent_name_expr:
return "<ExtendsNode: extends %s>" % self.parent_name_expr.token
return '<ExtendsNode: extends "%s">' % self.parent_name
def get_parent(self, context): def get_parent(self, context):
if self.parent_name_expr: if self.parent_name_expr:
self.parent_name = self.parent_name_expr.resolve(context) self.parent_name = self.parent_name_expr.resolve(context)
@ -49,7 +56,7 @@ class ExtendsNode(Node):
if not parent: if not parent:
error_msg = "Invalid template name in 'extends' tag: %r." % parent error_msg = "Invalid template name in 'extends' tag: %r." % parent
if self.parent_name_expr: if self.parent_name_expr:
error_msg += " Got this from the %r variable." % self.parent_name_expr #TODO nice repr. error_msg += " Got this from the '%s' variable." % self.parent_name_expr.token
raise TemplateSyntaxError, error_msg raise TemplateSyntaxError, error_msg
if hasattr(parent, 'render'): if hasattr(parent, 'render'):
return parent # parent is a Template object return parent # parent is a Template object
@ -62,7 +69,14 @@ class ExtendsNode(Node):
def render(self, context): def render(self, context):
compiled_parent = self.get_parent(context) compiled_parent = self.get_parent(context)
parent_is_child = isinstance(compiled_parent.nodelist[0], ExtendsNode) if len(compiled_parent.nodelist) > 1:
n0, n1 = compiled_parent.nodelist[:2]
else:
n0, n1 = compiled_parent.nodelist[0], None
parent_is_child = (isinstance(n0, ExtendsNode) or
(isinstance(n0, TextNode) and isinstance(n1, ExtendsNode)))
if parent_is_child:
extend_node = int(not isinstance(n0, ExtendsNode))
parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)]) parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)])
for block_node in self.nodelist.get_nodes_by_type(BlockNode): for block_node in self.nodelist.get_nodes_by_type(BlockNode):
# Check for a BlockNode with this node's name, and replace it if found. # Check for a BlockNode with this node's name, and replace it if found.
@ -74,7 +88,7 @@ class ExtendsNode(Node):
# add this BlockNode to the parent's ExtendsNode nodelist, so # add this BlockNode to the parent's ExtendsNode nodelist, so
# it'll be checked when the parent node's render() is called. # it'll be checked when the parent node's render() is called.
if parent_is_child: if parent_is_child:
compiled_parent.nodelist[0].nodelist.append(block_node) compiled_parent.nodelist[extend_node].nodelist.append(block_node)
else: else:
# Keep any existing parents and add a new one. Used by BlockNode. # Keep any existing parents and add a new one. Used by BlockNode.
parent_block.parent = block_node.parent parent_block.parent = block_node.parent

View File

@ -274,5 +274,5 @@ class Client:
Causes the authenticated user to be logged out. Causes the authenticated user to be logged out.
""" """
session = __import__(settings.SESSION_ENGINE, {}, {}, ['']).SessionStore() session = __import__(settings.SESSION_ENGINE, {}, {}, ['']).SessionStore()
session.delete(session_key=self.cookies['sessionid'].value) session.delete(session_key=self.cookies[settings.SESSION_COOKIE_NAME].value)
self.cookies = SimpleCookie() self.cookies = SimpleCookie()

View File

@ -72,6 +72,8 @@ class TestCase(unittest.TestCase):
self.client = Client() self.client = Client()
try: try:
self._pre_setup() self._pre_setup()
except (KeyboardInterrupt, SystemExit):
raise
except Exception: except Exception:
import sys import sys
result.addError(self, sys.exc_info()) result.addError(self, sys.exc_info())
@ -108,7 +110,7 @@ class TestCase(unittest.TestCase):
def assertContains(self, response, text, count=None, status_code=200): def assertContains(self, response, text, count=None, status_code=200):
""" """
Asserts that a response indicates that a page was retreived Asserts that a response indicates that a page was retrieved
successfully, (i.e., the HTTP status code was as expected), and that successfully, (i.e., the HTTP status code was as expected), and that
``text`` occurs ``count`` times in the content of the response. ``text`` occurs ``count`` times in the content of the response.
If ``count`` is None, the count doesn't matter - the assertion is true If ``count`` is None, the count doesn't matter - the assertion is true

View File

@ -2,6 +2,9 @@ class MergeDict(object):
""" """
A simple class for creating new "virtual" dictionaries that actually look A simple class for creating new "virtual" dictionaries that actually look
up values in more than one dictionary, passed in the constructor. up values in more than one dictionary, passed in the constructor.
If a key appears in more than one of the passed in dictionaries, only the
first occurrence will be used.
""" """
def __init__(self, *dicts): def __init__(self, *dicts):
self.dicts = dicts self.dicts = dicts
@ -25,11 +28,9 @@ class MergeDict(object):
def getlist(self, key): def getlist(self, key):
for dict_ in self.dicts: for dict_ in self.dicts:
try: if key in dict_.keys():
return dict_.getlist(key) return dict_.getlist(key)
except KeyError: return []
pass
raise KeyError
def items(self): def items(self):
item_list = [] item_list = []

View File

@ -98,5 +98,5 @@ def iri_to_uri(iri):
# section 3.1 of RFC 3987. # section 3.1 of RFC 3987.
if iri is None: if iri is None:
return iri return iri
return urllib.quote(smart_str(iri), safe='/#%[]=:;$&()+,!?') return urllib.quote(smart_str(iri), safe='/#%[]=:;$&()+,!?*')

View File

@ -53,7 +53,7 @@ class SyndicationFeed(object):
'title': to_unicode(title), 'title': to_unicode(title),
'link': iri_to_uri(link), 'link': iri_to_uri(link),
'description': to_unicode(description), 'description': to_unicode(description),
'language': force_unicode(language), 'language': to_unicode(language),
'author_email': to_unicode(author_email), 'author_email': to_unicode(author_email),
'author_name': to_unicode(author_name), 'author_name': to_unicode(author_name),
'author_link': iri_to_uri(author_link), 'author_link': iri_to_uri(author_link),

View File

@ -102,18 +102,23 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
if middle.startswith('www.') or ('@' not in middle and not middle.startswith('http://') and \ if middle.startswith('www.') or ('@' not in middle and not middle.startswith('http://') and \
len(middle) > 0 and middle[0] in string.ascii_letters + string.digits and \ len(middle) > 0 and middle[0] in string.ascii_letters + string.digits and \
(middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))): (middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))):
middle = '<a href="http://%s"%s>%s</a>' % ( middle = 'http://%s' % middle
urlquote(middle, safe='/&=:;#?+'), nofollow_attr,
trim_url(middle))
if middle.startswith('http://') or middle.startswith('https://'): if middle.startswith('http://') or middle.startswith('https://'):
middle = '<a href="%s"%s>%s</a>' % ( url = urlquote(middle, safe='/&=:;#?+*')
urlquote(middle, safe='/&=:;#?+'), nofollow_attr, if autoescape and not safe_input:
trim_url(middle)) url = escape(url)
if '@' in middle and not middle.startswith('www.') and \ trimmed_url = trim_url(middle)
not ':' in middle and simple_email_re.match(middle): middle = '<a href="%s"%s>%s</a>' % (url, nofollow_attr,
trimmed_url)
elif '@' in middle and not middle.startswith('www.') and \
not ':' in middle and simple_email_re.match(middle):
if autoescape:
middle = conditional_escape(middle)
middle = '<a href="mailto:%s">%s</a>' % (middle, middle) middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
if lead + middle + trail != word: if lead + middle + trail != word:
words[i] = lead + middle + trail if autoescape and not safe_input:
lead, trail = escape(lead), escape(trail)
words[i] = mark_safe('%s%s%s' % (lead, middle, trail))
elif autoescape and not safe_input: elif autoescape and not safe_input:
words[i] = escape(word) words[i] = escape(word)
elif safe_input: elif safe_input:

View File

@ -73,6 +73,12 @@ def technical_500_response(request, exc_type, exc_value, tb):
template_info = None template_info = None
template_does_not_exist = False template_does_not_exist = False
loader_debug_info = None loader_debug_info = None
# Handle deprecated string exceptions
if isinstance(exc_type, basestring):
exc_value = Exception('Deprecated String Exception: %r' % exc_type)
exc_type = type(exc_value)
if issubclass(exc_type, TemplateDoesNotExist): if issubclass(exc_type, TemplateDoesNotExist):
from django.template.loader import template_source_loaders from django.template.loader import template_source_loaders
template_does_not_exist = True template_does_not_exist = True
@ -192,9 +198,11 @@ def _get_lines_from_file(filename, lineno, context_lines, loader=None, module_na
Returns (pre_context_lineno, pre_context, context_line, post_context). Returns (pre_context_lineno, pre_context, context_line, post_context).
""" """
source = None source = None
if loader is not None: if loader is not None and hasattr(loader, "get_source"):
source = loader.get_source(module_name).splitlines() source = loader.get_source(module_name)
else: if source is not None:
source = source.splitlines()
if source is None:
try: try:
f = open(filename) f = open(filename)
try: try:
@ -431,11 +439,11 @@ TECHNICAL_500_TEMPLATE = """
{% if frame.context_line %} {% if frame.context_line %}
<div class="context" id="c{{ frame.id }}"> <div class="context" id="c{{ frame.id }}">
{% if frame.pre_context %} {% if frame.pre_context %}
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">{% for line in frame.pre_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endfor %}</ol> <ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">{% for line in frame.pre_context %}{% if line %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endif %}{% endfor %}</ol>
{% endif %} {% endif %}
<ol start="{{ frame.lineno }}" class="context-line"><li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ frame.context_line|escape }} <span>...</span></li></ol> <ol start="{{ frame.lineno }}" class="context-line"><li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ frame.context_line|escape }} <span>...</span></li></ol>
{% if frame.post_context %} {% if frame.post_context %}
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">{% for line in frame.post_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endfor %}</ol> <ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">{% for line in frame.post_context %}{% if line %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endif %}{% endfor %}</ol>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}

View File

@ -292,6 +292,14 @@ translation string. Example::
In this case, both the tag and the filter will see the already-translated In this case, both the tag and the filter will see the already-translated
string, so they don't need to be aware of translations. string, so they don't need to be aware of translations.
.. note::
In this example, the translation infrastructure will be passed the string
``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The
translated string will need to contain the comma so that the filter
parsing code knows how to split up the arguments. For example, a German
translator might translate the string ``"yes,no"`` as ``"ja,nein"``
(keeping the comma intact).
.. _Django templates: ../templates_python/ .. _Django templates: ../templates_python/
Working with lazy translation objects Working with lazy translation objects

View File

@ -113,10 +113,23 @@ postal code or a CPA_.
.. _CPA: http://www.correoargentino.com.ar/consulta_cpa/home.php .. _CPA: http://www.correoargentino.com.ar/consulta_cpa/home.php
ARDNIField
----------
A form field that validates input as a Documento Nacional de Identidad (DNI)
number.
ARCUITField
-----------
A form field that validates input as a Código Único de Identificación
Tributaria (CUIT) number.
ARProvinceSelect ARProvinceSelect
---------------- ----------------
A ``Select`` widget that uses a list of Argentina's provinces as its choices. A ``Select`` widget that uses a list of Argentina's provinces and autonomous
cities as its choices.
Australia (``django.contrib.localflavor.au``) Australia (``django.contrib.localflavor.au``)
============================================= =============================================

View File

@ -113,7 +113,7 @@ In addition, each generated form field has attributes set as follows:
``default`` value will be initially selected instead). ``default`` value will be initially selected instead).
Finally, note that you can override the form field used for a given model Finally, note that you can override the form field used for a given model
field. See "Overriding the default field types" below. field. See `Overriding the default field types`_ below.
A full example A full example
-------------- --------------
@ -295,7 +295,7 @@ model fields:
Overriding the default field types Overriding the default field types
---------------------------------- ----------------------------------
The default field types, as described in the "Field types" table above, are The default field types, as described in the `Field types`_ table above, are
sensible defaults. If you have a ``DateField`` in your model, chances are you'd sensible defaults. If you have a ``DateField`` in your model, chances are you'd
want that to be represented as a ``DateField`` in your form. But want that to be represented as a ``DateField`` in your form. But
``ModelForm`` gives you the flexibility of changing the form field type ``ModelForm`` gives you the flexibility of changing the form field type
@ -311,3 +311,12 @@ field, you could do the following::
... ...
... class Meta: ... class Meta:
... model = Article ... model = Article
If you want to override a field's default widget, then specify the ``widget``
parameter when declaring the form field::
>>> class ArticleForm(ModelForm):
... pub_date = DateField(widget=MyDateWidget())
...
... class Meta:
... model = Article

View File

@ -575,6 +575,10 @@ Three things to note about 404 views:
to the template: ``request_path``, which is the URL that resulted to the template: ``request_path``, which is the URL that resulted
in the 404. in the 404.
* The 404 view is passed a ``RequestContext`` and will have access to
variables supplied by your ``TEMPLATE_CONTEXT_PROCESSORS`` (e.g.
``MEDIA_URL``).
* If ``DEBUG`` is set to ``True`` (in your settings module), then your 404 * If ``DEBUG`` is set to ``True`` (in your settings module), then your 404
view will never be used, and the traceback will be displayed instead. view will never be used, and the traceback will be displayed instead.
@ -587,8 +591,9 @@ the view ``django.views.defaults.server_error``, which loads and renders the
template ``500.html``. template ``500.html``.
This means you need to define a ``500.html`` template in your root template This means you need to define a ``500.html`` template in your root template
directory. This template will be used for all server errors. The directory. This template will be used for all server errors. The default 500
default 500 view passes no variables to this template. view passes no variables to this template and is rendered with an empty
``Context`` to lessen the chance of additional errors.
This ``server_error`` view should suffice for 99% of Web applications, but if This ``server_error`` view should suffice for 99% of Web applications, but if
you want to override the view, you can specify ``handler500`` in your you want to override the view, you can specify ``handler500`` in your

View File

@ -22,16 +22,29 @@ Required arguments
Optional arguments Optional arguments
------------------ ------------------
``context`` ``dictionary``
A dictionary of values to add to the template context. By default, this A dictionary of values to add to the template context. By default, this
is an empty dictionary. If a value in the dictionary is callable, the is an empty dictionary. If a value in the dictionary is callable, the
view will call it just before rendering the template. view will call it just before rendering the template.
``context_instance``
The context instance to render the template with. By default, the template
will be rendered with a ``Context`` instance (filled with values from
``dictionary``). If you need to use `context processors`_, you will want to
render the template with a ``RequestContext`` instance instead. Your code
might look something like this::
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
``mimetype`` ``mimetype``
**New in Django development version:** The MIME type to use for the **New in Django development version:** The MIME type to use for the
resulting document. Defaults to the value of the ``DEFAULT_CONTENT_TYPE`` resulting document. Defaults to the value of the ``DEFAULT_CONTENT_TYPE``
setting. setting.
.. _`context processors`: ../templates_python/#subclassing-context-requestcontext
Example Example
------- -------
@ -57,8 +70,6 @@ This example is equivalent to::
r = HttpResponse(t.render(c), r = HttpResponse(t.render(c),
mimetype="application/xhtml+xml") mimetype="application/xhtml+xml")
.. _an HttpResponse object: ../request_response/#httpresponse-objects
``get_object_or_404`` ``get_object_or_404``
===================== =====================

View File

@ -13,8 +13,16 @@ class Person(models.Model):
return u"%s %s" % (self.first_name, self.last_name) return u"%s %s" % (self.first_name, self.last_name)
def pre_save_nokwargs_test(sender, instance):
print 'pre_save_nokwargs signal'
def post_save_nokwargs_test(sender, instance):
print 'post_save_nokwargs signal'
def pre_save_test(sender, instance, **kwargs): def pre_save_test(sender, instance, **kwargs):
print 'pre_save signal,', instance print 'pre_save signal,', instance
if kwargs.get('raw'):
print 'Is raw'
def post_save_test(sender, instance, **kwargs): def post_save_test(sender, instance, **kwargs):
print 'post_save signal,', instance print 'post_save signal,', instance
@ -23,6 +31,8 @@ def post_save_test(sender, instance, **kwargs):
print 'Is created' print 'Is created'
else: else:
print 'Is updated' print 'Is updated'
if kwargs.get('raw'):
print 'Is raw'
def pre_delete_test(sender, instance, **kwargs): def pre_delete_test(sender, instance, **kwargs):
print 'pre_delete signal,', instance print 'pre_delete signal,', instance
@ -33,6 +43,8 @@ def post_delete_test(sender, instance, **kwargs):
print 'instance.id is None: %s' % (instance.id == None) print 'instance.id is None: %s' % (instance.id == None)
__test__ = {'API_TESTS':""" __test__ = {'API_TESTS':"""
>>> dispatcher.connect(pre_save_nokwargs_test, signal=models.signals.pre_save)
>>> dispatcher.connect(post_save_nokwargs_test, signal=models.signals.post_save)
>>> dispatcher.connect(pre_save_test, signal=models.signals.pre_save) >>> dispatcher.connect(pre_save_test, signal=models.signals.pre_save)
>>> dispatcher.connect(post_save_test, signal=models.signals.post_save) >>> dispatcher.connect(post_save_test, signal=models.signals.post_save)
>>> dispatcher.connect(pre_delete_test, signal=models.signals.pre_delete) >>> dispatcher.connect(pre_delete_test, signal=models.signals.pre_delete)
@ -40,16 +52,29 @@ __test__ = {'API_TESTS':"""
>>> p1 = Person(first_name='John', last_name='Smith') >>> p1 = Person(first_name='John', last_name='Smith')
>>> p1.save() >>> p1.save()
pre_save_nokwargs signal
pre_save signal, John Smith pre_save signal, John Smith
post_save_nokwargs signal
post_save signal, John Smith post_save signal, John Smith
Is created Is created
>>> p1.first_name = 'Tom' >>> p1.first_name = 'Tom'
>>> p1.save() >>> p1.save()
pre_save_nokwargs signal
pre_save signal, Tom Smith pre_save signal, Tom Smith
post_save_nokwargs signal
post_save signal, Tom Smith post_save signal, Tom Smith
Is updated Is updated
>>> p1.save(raw=True)
pre_save_nokwargs signal
pre_save signal, Tom Smith
Is raw
post_save_nokwargs signal
post_save signal, Tom Smith
Is updated
Is raw
>>> p1.delete() >>> p1.delete()
pre_delete signal, Tom Smith pre_delete signal, Tom Smith
instance.id is not None: True instance.id is not None: True
@ -59,13 +84,17 @@ instance.id is None: False
>>> p2 = Person(first_name='James', last_name='Jones') >>> p2 = Person(first_name='James', last_name='Jones')
>>> p2.id = 99999 >>> p2.id = 99999
>>> p2.save() >>> p2.save()
pre_save_nokwargs signal
pre_save signal, James Jones pre_save signal, James Jones
post_save_nokwargs signal
post_save signal, James Jones post_save signal, James Jones
Is created Is created
>>> p2.id = 99998 >>> p2.id = 99998
>>> p2.save() >>> p2.save()
pre_save_nokwargs signal
pre_save signal, James Jones pre_save signal, James Jones
post_save_nokwargs signal
post_save signal, James Jones post_save signal, James Jones
Is created Is created
@ -78,6 +107,8 @@ instance.id is None: False
>>> Person.objects.all() >>> Person.objects.all()
[<Person: James Jones>] [<Person: James Jones>]
>>> dispatcher.disconnect(pre_save_nokwargs_test, signal=models.signals.pre_save)
>>> dispatcher.disconnect(post_save_nokwargs_test, signal=models.signals.post_save)
>>> dispatcher.disconnect(post_delete_test, signal=models.signals.post_delete) >>> dispatcher.disconnect(post_delete_test, signal=models.signals.post_delete)
>>> dispatcher.disconnect(pre_delete_test, signal=models.signals.pre_delete) >>> dispatcher.disconnect(pre_delete_test, signal=models.signals.pre_delete)
>>> dispatcher.disconnect(post_save_test, signal=models.signals.post_save) >>> dispatcher.disconnect(post_save_test, signal=models.signals.post_save)

View File

@ -20,6 +20,19 @@
>>> md2['chris'] >>> md2['chris']
'cool' 'cool'
MergeDict can merge MultiValueDicts
>>> multi1 = MultiValueDict({'key1': ['value1'], 'key2': ['value2', 'value3']})
>>> multi2 = MultiValueDict({'key2': ['value4'], 'key4': ['value5', 'value6']})
>>> mm = MergeDict(multi1, multi2)
# Although 'key2' appears in both dictionaries, only the first value is used.
>>> mm.getlist('key2')
['value2', 'value3']
>>> mm.getlist('key4')
['value5', 'value6']
>>> mm.getlist('undefined')
[]
### MultiValueDict ########################################################## ### MultiValueDict ##########################################################
>>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']})

View File

@ -98,8 +98,8 @@ def get_filter_tests():
'filter-upper01': ('{% autoescape off %}{{ a|upper }} {{ b|upper }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a &amp; b")}, u"A & B A &AMP; B"), 'filter-upper01': ('{% autoescape off %}{{ a|upper }} {{ b|upper }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a &amp; b")}, u"A & B A &AMP; B"),
'filter-upper02': ('{{ a|upper }} {{ b|upper }}', {"a": "a & b", "b": mark_safe("a &amp; b")}, u"A &amp; B A &amp;AMP; B"), 'filter-upper02': ('{{ a|upper }} {{ b|upper }}', {"a": "a & b", "b": mark_safe("a &amp; b")}, u"A &amp; B A &amp;AMP; B"),
'filter-urlize01': ('{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}', {"a": "http://example.com/x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/x=&y=" rel="nofollow">http://example.com/x=&y=</a> <a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'), 'filter-urlize01': ('{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&amp;y=")}, u'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> <a href="http://example.com?x=&amp;y=" rel="nofollow">http://example.com?x=&amp;y=</a>'),
'filter-urlize02': ('{{ a|urlize }} {{ b|urlize }}', {"a": "http://example.com/x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/x=&y=" rel="nofollow">http://example.com/x=&amp;y=</a> <a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'), 'filter-urlize02': ('{{ a|urlize }} {{ b|urlize }}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&amp;y=")}, u'<a href="http://example.com/?x=&amp;y=" rel="nofollow">http://example.com/?x=&amp;y=</a> <a href="http://example.com?x=&amp;y=" rel="nofollow">http://example.com?x=&amp;y=</a>'),
'filter-urlize03': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": mark_safe("a &amp; b")}, 'a &amp; b'), 'filter-urlize03': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": mark_safe("a &amp; b")}, 'a &amp; b'),
'filter-urlize04': ('{{ a|urlize }}', {"a": mark_safe("a &amp; b")}, 'a &amp; b'), 'filter-urlize04': ('{{ a|urlize }}', {"a": mark_safe("a &amp; b")}, 'a &amp; b'),
@ -108,8 +108,12 @@ def get_filter_tests():
'filter-urlize05': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": "<script>alert('foo')</script>"}, "<script>alert('foo')</script>"), 'filter-urlize05': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": "<script>alert('foo')</script>"}, "<script>alert('foo')</script>"),
'filter-urlize06': ('{{ a|urlize }}', {"a": "<script>alert('foo')</script>"}, '&lt;script&gt;alert(&#39;foo&#39;)&lt;/script&gt;'), 'filter-urlize06': ('{{ a|urlize }}', {"a": "<script>alert('foo')</script>"}, '&lt;script&gt;alert(&#39;foo&#39;)&lt;/script&gt;'),
'filter-urlizetrunc01': ('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('&quot;Safe&quot; http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> &quot;Safe&quot; <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'), # mailto: testing for urlize
'filter-urlizetrunc02': ('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('&quot;Safe&quot; http://example.com?x=&y=')}, u'&quot;Unsafe&quot; <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> &quot;Safe&quot; <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'), 'filter-urlize07': ('{{ a|urlize }}', {"a": "Email me at me@example.com"}, 'Email me at <a href="mailto:me@example.com">me@example.com</a>'),
'filter-urlize08': ('{{ a|urlize }}', {"a": "Email me at <me@example.com>"}, 'Email me at &lt;<a href="mailto:me@example.com">me@example.com</a>&gt;'),
'filter-urlizetrunc01': ('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('&quot;Safe&quot; http://example.com?x=&amp;y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> &quot;Safe&quot; <a href="http://example.com?x=&amp;y=" rel="nofollow">http:...</a>'),
'filter-urlizetrunc02': ('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('&quot;Safe&quot; http://example.com?x=&amp;y=')}, u'&quot;Unsafe&quot; <a href="http://example.com/x=&amp;y=" rel="nofollow">http:...</a> &quot;Safe&quot; <a href="http://example.com?x=&amp;y=" rel="nofollow">http:...</a>'),
'filter-wordcount01': ('{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a &amp; b")}, "3 3"), 'filter-wordcount01': ('{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a &amp; b")}, "3 3"),
'filter-wordcount02': ('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a &amp; b")}, "3 3"), 'filter-wordcount02': ('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a &amp; b")}, "3 3"),

View File

@ -736,7 +736,7 @@ class Templates(unittest.TestCase):
'i18n09': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"), 'i18n09': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"),
# translation of a variable with a translated filter # translation of a variable with a translated filter
'i18n10': ('{{ bool|yesno:_("ja,nein") }}', {'bool': True}, 'ja'), 'i18n10': ('{{ bool|yesno:_("yes,no,maybe") }}', {'bool': True, 'LANGUAGE_CODE': 'de'}, 'Ja'),
# translation of a variable with a non-translated filter # translation of a variable with a non-translated filter
'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'), 'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'),