mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
newforms-admin: Merged to [6013]
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@6014 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a6784e6821
commit
22e160945a
6
AUTHORS
6
AUTHORS
@ -95,6 +95,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Alex Dedul
|
Alex Dedul
|
||||||
deric@monowerks.com
|
deric@monowerks.com
|
||||||
Max Derkachev <mderk@yandex.ru>
|
Max Derkachev <mderk@yandex.ru>
|
||||||
|
Sander Dijkhuis <sander.dijkhuis@gmail.com>
|
||||||
Jordan Dimov <s3x3y1@gmail.com>
|
Jordan Dimov <s3x3y1@gmail.com>
|
||||||
dne@mayonnaise.net
|
dne@mayonnaise.net
|
||||||
Maximillian Dornseif <md@hudora.de>
|
Maximillian Dornseif <md@hudora.de>
|
||||||
@ -137,6 +138,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Joe Heck <http://www.rhonabwy.com/wp/>
|
Joe Heck <http://www.rhonabwy.com/wp/>
|
||||||
Joel Heenan <joelh-django@planetjoel.com>
|
Joel Heenan <joelh-django@planetjoel.com>
|
||||||
hipertracker@gmail.com
|
hipertracker@gmail.com
|
||||||
|
Deryck Hodge <http://www.devurandom.org/>
|
||||||
Brett Hoerner <bretthoerner@bretthoerner.com>
|
Brett Hoerner <bretthoerner@bretthoerner.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>
|
||||||
@ -204,6 +206,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Andreas Mock <andreas.mock@web.de>
|
Andreas Mock <andreas.mock@web.de>
|
||||||
Reza Mohammadi <reza@zeerak.ir>
|
Reza Mohammadi <reza@zeerak.ir>
|
||||||
Aljosa Mohorovic <aljosa.mohorovic@gmail.com>
|
Aljosa Mohorovic <aljosa.mohorovic@gmail.com>
|
||||||
|
Ramiro Morales <rm0@gmx.net>
|
||||||
Eric Moritz <http://eric.themoritzfamily.com/>
|
Eric Moritz <http://eric.themoritzfamily.com/>
|
||||||
mrmachine <real.human@mrmachine.net>
|
mrmachine <real.human@mrmachine.net>
|
||||||
Robin Munn <http://www.geekforgod.com/>
|
Robin Munn <http://www.geekforgod.com/>
|
||||||
@ -213,6 +216,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Fraser Nevett <mail@nevett.org>
|
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>
|
||||||
|
Todd O'Bryan <toddobryan@mac.com>
|
||||||
oggie rob <oz.robharvey@gmail.com>
|
oggie rob <oz.robharvey@gmail.com>
|
||||||
Jay Parlar <parlar@gmail.com>
|
Jay Parlar <parlar@gmail.com>
|
||||||
pavithran s <pavithran.s@gmail.com>
|
pavithran s <pavithran.s@gmail.com>
|
||||||
@ -228,10 +232,10 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Daniel Poelzleithner <http://poelzi.org/>
|
Daniel Poelzleithner <http://poelzi.org/>
|
||||||
polpak@yahoo.com
|
polpak@yahoo.com
|
||||||
Matthias Pronk <django@masida.nl>
|
Matthias Pronk <django@masida.nl>
|
||||||
|
Jyrki Pulliainen <jyrki.pulliainen@gmail.com>
|
||||||
Johann Queuniet <johann.queuniet@adh.naellia.eu>
|
Johann Queuniet <johann.queuniet@adh.naellia.eu>
|
||||||
J. Rademaker
|
J. Rademaker
|
||||||
Michael Radziej <mir@noris.de>
|
Michael Radziej <mir@noris.de>
|
||||||
Ramiro Morales <rm0@gmx.net>
|
|
||||||
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
|
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
|
||||||
Brian Ray <http://brianray.chipy.org/>
|
Brian Ray <http://brianray.chipy.org/>
|
||||||
remco@diji.biz
|
remco@diji.biz
|
||||||
|
@ -4,5 +4,6 @@ def get_version():
|
|||||||
"Returns the version as a human-format string."
|
"Returns the version as a human-format string."
|
||||||
v = '.'.join([str(i) for i in VERSION[:-1]])
|
v = '.'.join([str(i) for i in VERSION[:-1]])
|
||||||
if VERSION[-1]:
|
if VERSION[-1]:
|
||||||
v += '-' + VERSION[-1]
|
from django.utils.version import get_svn_revision
|
||||||
|
v = '%s-%s-%s' % (v, VERSION[-1], get_svn_revision())
|
||||||
return v
|
return v
|
||||||
|
@ -17,7 +17,7 @@ def login(request, template_name='registration/login.html'):
|
|||||||
errors = manipulator.get_validation_errors(request.POST)
|
errors = manipulator.get_validation_errors(request.POST)
|
||||||
if not errors:
|
if not errors:
|
||||||
# Light security check -- make sure redirect_to isn't garbage.
|
# Light security check -- make sure redirect_to isn't garbage.
|
||||||
if not redirect_to or '://' in redirect_to or ' ' in redirect_to:
|
if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
redirect_to = settings.LOGIN_REDIRECT_URL
|
redirect_to = settings.LOGIN_REDIRECT_URL
|
||||||
from django.contrib.auth import login
|
from django.contrib.auth import login
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
from django.utils.translation import ungettext, ugettext as _
|
from django.utils.translation import ungettext, ugettext as _
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
from django import template
|
from django import template
|
||||||
|
from django.template import defaultfilters
|
||||||
|
from django.conf import settings
|
||||||
|
from datetime import date, timedelta
|
||||||
import re
|
import re
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
@ -67,3 +70,27 @@ def apnumber(value):
|
|||||||
return value
|
return value
|
||||||
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
|
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
|
||||||
register.filter(apnumber)
|
register.filter(apnumber)
|
||||||
|
|
||||||
|
def naturalday(value, arg=None):
|
||||||
|
"""
|
||||||
|
For date values that are tomorrow, today or yesterday compared to
|
||||||
|
present day returns representing string. Otherwise, returns a string
|
||||||
|
formatted according to settings.DATE_FORMAT.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
value = date(value.year, value.month, value.day)
|
||||||
|
except AttributeError:
|
||||||
|
# Passed value wasn't a date object
|
||||||
|
return value
|
||||||
|
except ValueError:
|
||||||
|
# Date arguments out of range
|
||||||
|
return value
|
||||||
|
delta = value - date.today()
|
||||||
|
if delta.days == 0:
|
||||||
|
return _(u'today')
|
||||||
|
elif delta.days == 1:
|
||||||
|
return _(u'tomorrow')
|
||||||
|
elif delta.days == -1:
|
||||||
|
return _(u'yesterday')
|
||||||
|
return defaultfilters.date(value, arg)
|
||||||
|
register.filter(naturalday)
|
||||||
|
@ -24,7 +24,7 @@ class Command(NoArgsCommand):
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
sql_list = sql_flush(self.style)
|
sql_list = sql_flush(self.style, only_django=True)
|
||||||
|
|
||||||
if interactive:
|
if interactive:
|
||||||
confirm = raw_input("""You have requested a flush of the database.
|
confirm = raw_input("""You have requested a flush of the database.
|
||||||
|
@ -30,7 +30,7 @@ class Command(BaseCommand):
|
|||||||
raise CommandError("%r is not a valid port number." % port)
|
raise CommandError("%r is not a valid port number." % port)
|
||||||
|
|
||||||
use_reloader = options.get('use_reloader', True)
|
use_reloader = options.get('use_reloader', True)
|
||||||
admin_media_dir = options.get('admin_media_dir', '')
|
admin_media_path = options.get('admin_media_path', '')
|
||||||
shutdown_message = options.get('shutdown_message', '')
|
shutdown_message = options.get('shutdown_message', '')
|
||||||
quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
|
quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C'
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class Command(BaseCommand):
|
|||||||
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:
|
||||||
path = admin_media_dir or django.__path__[0] + '/contrib/admin/media'
|
path = admin_media_path or django.__path__[0] + '/contrib/admin/media'
|
||||||
handler = AdminMediaHandler(WSGIHandler(), path)
|
handler = AdminMediaHandler(WSGIHandler(), path)
|
||||||
run(addr, int(port), handler)
|
run(addr, int(port), handler)
|
||||||
except WSGIServerException, e:
|
except WSGIServerException, e:
|
||||||
|
@ -7,4 +7,4 @@ class Command(NoArgsCommand):
|
|||||||
|
|
||||||
def handle_noargs(self, **options):
|
def handle_noargs(self, **options):
|
||||||
from django.core.management.sql import sql_flush
|
from django.core.management.sql import sql_flush
|
||||||
return '\n'.join(sql_flush(self.style))
|
return '\n'.join(sql_flush(self.style, only_django=True))
|
||||||
|
@ -13,6 +13,25 @@ def table_list():
|
|||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
return get_introspection_module().get_table_list(cursor)
|
return get_introspection_module().get_table_list(cursor)
|
||||||
|
|
||||||
|
def django_table_list(only_existing=False):
|
||||||
|
"""
|
||||||
|
Returns a list of all table names that have associated Django models and
|
||||||
|
are in INSTALLED_APPS.
|
||||||
|
|
||||||
|
If only_existing is True, the resulting list will only include the tables
|
||||||
|
that actually exist in the database.
|
||||||
|
"""
|
||||||
|
from django.db import models
|
||||||
|
tables = []
|
||||||
|
for app in models.get_apps():
|
||||||
|
for model in models.get_models(app):
|
||||||
|
tables.append(model._meta.db_table)
|
||||||
|
tables.extend([f.m2m_db_table() for f in model._meta.many_to_many])
|
||||||
|
if only_existing:
|
||||||
|
existing = table_list()
|
||||||
|
tables = [t for t in tables if t in existing]
|
||||||
|
return tables
|
||||||
|
|
||||||
def installed_models(table_list):
|
def installed_models(table_list):
|
||||||
"Returns a set of all models that are installed, given a list of existing table names."
|
"Returns a set of all models that are installed, given a list of existing table names."
|
||||||
from django.db import connection, models
|
from django.db import connection, models
|
||||||
@ -181,10 +200,19 @@ def sql_reset(app, style):
|
|||||||
"Returns a list of the DROP TABLE SQL, then the CREATE TABLE SQL, for the given module."
|
"Returns a list of the DROP TABLE SQL, then the CREATE TABLE SQL, for the given module."
|
||||||
return sql_delete(app, style) + sql_all(app, style)
|
return sql_delete(app, style) + sql_all(app, style)
|
||||||
|
|
||||||
def sql_flush(style):
|
def sql_flush(style, only_django=False):
|
||||||
"Returns a list of the SQL statements used to flush the database."
|
"""
|
||||||
|
Returns a list of the SQL statements used to flush the database.
|
||||||
|
|
||||||
|
If only_django is True, then only table names that have associated Django
|
||||||
|
models and are in INSTALLED_APPS will be included.
|
||||||
|
"""
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
statements = connection.ops.sql_flush(style, table_list(), sequence_list())
|
if only_django:
|
||||||
|
tables = django_table_list()
|
||||||
|
else:
|
||||||
|
tables = table_list()
|
||||||
|
statements = connection.ops.sql_flush(style, tables, sequence_list())
|
||||||
return statements
|
return statements
|
||||||
|
|
||||||
def sql_custom(app):
|
def sql_custom(app):
|
||||||
|
@ -8,6 +8,7 @@ ImproperlyConfigured.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.db.backends import BaseDatabaseFeatures, BaseDatabaseOperations
|
||||||
|
|
||||||
def complain(*args, **kwargs):
|
def complain(*args, **kwargs):
|
||||||
raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet."
|
raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet."
|
||||||
@ -21,13 +22,12 @@ class DatabaseError(Exception):
|
|||||||
class IntegrityError(DatabaseError):
|
class IntegrityError(DatabaseError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class ComplainOnGetattr(object):
|
class DatabaseOperations(BaseDatabaseOperations):
|
||||||
def __getattr__(self, *args, **kwargs):
|
quote_name = complain
|
||||||
complain()
|
|
||||||
|
|
||||||
class DatabaseWrapper(object):
|
class DatabaseWrapper(object):
|
||||||
features = ComplainOnGetattr()
|
features = BaseDatabaseFeatures()
|
||||||
ops = ComplainOnGetattr()
|
ops = DatabaseOperations()
|
||||||
operators = {}
|
operators = {}
|
||||||
cursor = complain
|
cursor = complain
|
||||||
_commit = complain
|
_commit = complain
|
||||||
|
@ -70,7 +70,7 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||||||
return "DROP SEQUENCE %s;" % self.quote_name(get_sequence_name(table))
|
return "DROP SEQUENCE %s;" % self.quote_name(get_sequence_name(table))
|
||||||
|
|
||||||
def field_cast_sql(self, db_type):
|
def field_cast_sql(self, db_type):
|
||||||
if db_type.endswith('LOB'):
|
if db_type and db_type.endswith('LOB'):
|
||||||
return "DBMS_LOB.SUBSTR(%s)"
|
return "DBMS_LOB.SUBSTR(%s)"
|
||||||
else:
|
else:
|
||||||
return "%s"
|
return "%s"
|
||||||
|
@ -102,9 +102,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||||||
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
|
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
|
||||||
cursor.execute("SET client_encoding to 'UNICODE'")
|
cursor.execute("SET client_encoding to 'UNICODE'")
|
||||||
cursor = UnicodeCursorWrapper(cursor, 'utf-8')
|
cursor = UnicodeCursorWrapper(cursor, 'utf-8')
|
||||||
if self.ops.postgres_version is None:
|
|
||||||
cursor.execute("SELECT version()")
|
|
||||||
self.ops.postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')]
|
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def typecast_string(s):
|
def typecast_string(s):
|
||||||
|
@ -4,8 +4,17 @@ from django.db.backends import BaseDatabaseOperations
|
|||||||
# used by both the 'postgresql' and 'postgresql_psycopg2' backends.
|
# used by both the 'postgresql' and 'postgresql_psycopg2' backends.
|
||||||
|
|
||||||
class DatabaseOperations(BaseDatabaseOperations):
|
class DatabaseOperations(BaseDatabaseOperations):
|
||||||
def __init__(self, postgres_version=None):
|
def __init__(self):
|
||||||
self.postgres_version = postgres_version
|
self._postgres_version = None
|
||||||
|
|
||||||
|
def _get_postgres_version(self):
|
||||||
|
if self._postgres_version is None:
|
||||||
|
from django.db import connection
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute("SELECT version()")
|
||||||
|
self._postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')]
|
||||||
|
return self._postgres_version
|
||||||
|
postgres_version = property(_get_postgres_version)
|
||||||
|
|
||||||
def date_extract_sql(self, lookup_type, field_name):
|
def date_extract_sql(self, lookup_type, field_name):
|
||||||
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
|
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
|
||||||
@ -53,26 +62,12 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||||||
table_name = sequence_info['table']
|
table_name = sequence_info['table']
|
||||||
column_name = sequence_info['column']
|
column_name = sequence_info['column']
|
||||||
if column_name and len(column_name) > 0:
|
if column_name and len(column_name) > 0:
|
||||||
# sequence name in this case will be <table>_<column>_seq
|
sequence_name = '%s_%s_seq' % (table_name, column_name)
|
||||||
sql.append("%s %s %s %s %s %s;" % \
|
|
||||||
(style.SQL_KEYWORD('ALTER'),
|
|
||||||
style.SQL_KEYWORD('SEQUENCE'),
|
|
||||||
style.SQL_FIELD(self.quote_name('%s_%s_seq' % (table_name, column_name))),
|
|
||||||
style.SQL_KEYWORD('RESTART'),
|
|
||||||
style.SQL_KEYWORD('WITH'),
|
|
||||||
style.SQL_FIELD('1')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# sequence name in this case will be <table>_id_seq
|
sequence_name = '%s_id_seq' % table_name
|
||||||
sql.append("%s %s %s %s %s %s;" % \
|
sql.append("%s setval('%s', 1, false);" % \
|
||||||
(style.SQL_KEYWORD('ALTER'),
|
(style.SQL_KEYWORD('SELECT'),
|
||||||
style.SQL_KEYWORD('SEQUENCE'),
|
style.SQL_FIELD(self.quote_name(sequence_name)))
|
||||||
style.SQL_FIELD(self.quote_name('%s_id_seq' % table_name)),
|
|
||||||
style.SQL_KEYWORD('RESTART'),
|
|
||||||
style.SQL_KEYWORD('WITH'),
|
|
||||||
style.SQL_FIELD('1')
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return sql
|
return sql
|
||||||
else:
|
else:
|
||||||
|
@ -64,7 +64,4 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||||||
cursor.tzinfo_factory = None
|
cursor.tzinfo_factory = None
|
||||||
if set_tz:
|
if set_tz:
|
||||||
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
|
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
|
||||||
if self.ops.postgres_version is None:
|
|
||||||
cursor.execute("SELECT version()")
|
|
||||||
self.ops.postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')]
|
|
||||||
return cursor
|
return cursor
|
||||||
|
39
django/utils/version.py
Normal file
39
django/utils/version.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import django
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
|
||||||
|
def get_svn_revision(path=None):
|
||||||
|
"""
|
||||||
|
Returns the SVN revision in the form SVN-XXXX,
|
||||||
|
where XXXX is the revision number.
|
||||||
|
|
||||||
|
Returns SVN-unknown if anything goes wrong, such as an unexpected
|
||||||
|
format of internal SVN files.
|
||||||
|
|
||||||
|
If path is provided, it should be a directory whose SVN info you want to
|
||||||
|
inspect. If it's not provided, this will use the root django/ package
|
||||||
|
directory.
|
||||||
|
"""
|
||||||
|
rev = None
|
||||||
|
if path is None:
|
||||||
|
path = django.__path__[0]
|
||||||
|
entries_path = '%s/.svn/entries' % path
|
||||||
|
|
||||||
|
if os.path.exists(entries_path):
|
||||||
|
entries = open(entries_path, 'r').read()
|
||||||
|
# Versions >= 7 of the entries file are flat text. The first line is
|
||||||
|
# the version number. The next set of digits after 'dir' is the revision.
|
||||||
|
if re.match('(\d+)', entries):
|
||||||
|
rev_match = re.search('\d+\s+dir\s+(\d+)', entries)
|
||||||
|
if rev_match:
|
||||||
|
rev = rev_match.groups()[0]
|
||||||
|
# Older XML versions of the file specify revision as an attribute of
|
||||||
|
# the first entries node.
|
||||||
|
else:
|
||||||
|
from xml.dom import minidom
|
||||||
|
dom = minidom.parse(entries_path)
|
||||||
|
rev = dom.getElementsByTagName('entry')[0].getAttribute('revision')
|
||||||
|
|
||||||
|
if rev:
|
||||||
|
return u'SVN-%s' % rev
|
||||||
|
return u'SVN-unknown'
|
@ -138,6 +138,29 @@ Examples:
|
|||||||
|
|
||||||
You can pass in either an integer or a string representation of an integer.
|
You can pass in either an integer or a string representation of an integer.
|
||||||
|
|
||||||
|
naturalday
|
||||||
|
----------
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
For dates that are the current day or within one day, return "today",
|
||||||
|
"tomorrow" or "yesterday", as appropriate. Otherwise, format the date using
|
||||||
|
the passed in format string.
|
||||||
|
|
||||||
|
**Argument:** Date formatting string as described in default tag now_.
|
||||||
|
|
||||||
|
.. _now: ../templates/#now
|
||||||
|
|
||||||
|
Examples (when 'today' is 17 Feb 2007):
|
||||||
|
|
||||||
|
* ``16 Feb 2007`` becomes ``yesterday``.
|
||||||
|
* ``17 Feb 2007`` becomes ``today``.
|
||||||
|
* ``18 Feb 2007`` becomes ``tomorrow``.
|
||||||
|
* Any other day is formatted according to given argument or the
|
||||||
|
`DATE_FORMAT`_ setting if no argument is given.
|
||||||
|
|
||||||
|
.. _DATE_FORMAT: ../settings/#date_format
|
||||||
|
|
||||||
flatpages
|
flatpages
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@ -207,14 +207,23 @@ the database until you explicitly call ``save()``.
|
|||||||
|
|
||||||
The ``save()`` method has no return value.
|
The ``save()`` method has no return value.
|
||||||
|
|
||||||
Updating ``ForeignKey`` fields works exactly the same way; simply assign an
|
Saving ForeignKey and ManyToManyField fields
|
||||||
object of the right type to the field in question::
|
--------------------------------------------
|
||||||
|
|
||||||
joe = Author.objects.create(name="Joe")
|
Updating ``ForeignKey`` fields works exactly the same way as saving a normal
|
||||||
entry.author = joe
|
field; simply assign an object of the right type to the field in question::
|
||||||
|
|
||||||
|
cheese_blog = Blog.objects.get(name="Cheddar Talk")
|
||||||
|
entry.blog = cheese_blog
|
||||||
entry.save()
|
entry.save()
|
||||||
|
|
||||||
Django will complain if you try to assign an object of the wrong type.
|
Updating a ``ManyToManyField`` works a little differently; use the ``add()``
|
||||||
|
method on the field to add a record to the relation::
|
||||||
|
|
||||||
|
joe = Author.objects.create(name="Joe")
|
||||||
|
entry.authors.add(joe)
|
||||||
|
|
||||||
|
Django will complain if you try to assign or add an object of the wrong type.
|
||||||
|
|
||||||
How Django knows to UPDATE vs. INSERT
|
How Django knows to UPDATE vs. INSERT
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
@ -124,6 +124,13 @@ executed. This means that all data will be removed from the database, any
|
|||||||
post-synchronization handlers will be re-executed, and the ``initial_data``
|
post-synchronization handlers will be re-executed, and the ``initial_data``
|
||||||
fixture will be re-installed.
|
fixture will be re-installed.
|
||||||
|
|
||||||
|
The behavior of this command has changed in the Django development version.
|
||||||
|
Previously, this command cleared *every* table in the database, including any
|
||||||
|
table that Django didn't know about (i.e., tables that didn't have associated
|
||||||
|
models and/or weren't in ``INSTALLED_APPS``). Now, the command only clears
|
||||||
|
tables that are represented by Django models and are activated in
|
||||||
|
``INSTALLED_APPS``.
|
||||||
|
|
||||||
inspectdb
|
inspectdb
|
||||||
---------
|
---------
|
||||||
|
|
||||||
@ -240,6 +247,7 @@ Executes the equivalent of ``sqlreset`` for the given appnames.
|
|||||||
|
|
||||||
runfcgi [options]
|
runfcgi [options]
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Starts a set of FastCGI processes suitable for use with any web server
|
Starts a set of FastCGI processes suitable for use with any web server
|
||||||
which supports the FastCGI protocol. See the `FastCGI deployment
|
which supports the FastCGI protocol. See the `FastCGI deployment
|
||||||
documentation`_ for details. Requires the Python FastCGI module from
|
documentation`_ for details. Requires the Python FastCGI module from
|
||||||
@ -337,7 +345,7 @@ Refer to the description of ``sqlcustom`` for an explanation of how to
|
|||||||
specify initial data.
|
specify initial data.
|
||||||
|
|
||||||
sqlclear [appname appname ...]
|
sqlclear [appname appname ...]
|
||||||
--------------------------------------
|
------------------------------
|
||||||
|
|
||||||
Prints the DROP TABLE SQL statements for the given appnames.
|
Prints the DROP TABLE SQL statements for the given appnames.
|
||||||
|
|
||||||
@ -360,18 +368,23 @@ table modifications, or insert any SQL functions into the database.
|
|||||||
|
|
||||||
Note that the order in which the SQL files are processed is undefined.
|
Note that the order in which the SQL files are processed is undefined.
|
||||||
|
|
||||||
|
sqlflush
|
||||||
|
--------
|
||||||
|
|
||||||
|
Prints the SQL statements that would be executed for the `flush`_ command.
|
||||||
|
|
||||||
sqlindexes [appname appname ...]
|
sqlindexes [appname appname ...]
|
||||||
----------------------------------------
|
--------------------------------
|
||||||
|
|
||||||
Prints the CREATE INDEX SQL statements for the given appnames.
|
Prints the CREATE INDEX SQL statements for the given appnames.
|
||||||
|
|
||||||
sqlreset [appname appname ...]
|
sqlreset [appname appname ...]
|
||||||
--------------------------------------
|
------------------------------
|
||||||
|
|
||||||
Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames.
|
Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames.
|
||||||
|
|
||||||
sqlsequencereset [appname appname ...]
|
sqlsequencereset [appname appname ...]
|
||||||
----------------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
Prints the SQL statements for resetting sequences for the given
|
Prints the SQL statements for resetting sequences for the given
|
||||||
appnames.
|
appnames.
|
||||||
|
@ -204,10 +204,6 @@ out a few points, we want to make sure they reflect the final state of things
|
|||||||
at Django 1.0, not some intermediary step. In other words, we don't want to
|
at Django 1.0, not some intermediary step. In other words, we don't want to
|
||||||
spend a lot of energy creating screencasts yet, because Django APIs will shift.
|
spend a lot of energy creating screencasts yet, because Django APIs will shift.
|
||||||
|
|
||||||
In the meantime, though, check out this `unofficial Django screencast`_.
|
|
||||||
|
|
||||||
.. _unofficial Django screencast: http://www.throwingbeans.org/django_screencasts.html
|
|
||||||
|
|
||||||
Is Django a content-management-system (CMS)?
|
Is Django a content-management-system (CMS)?
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ development version. See the `Django 0.96 documentation`_ for the old behavior.
|
|||||||
``ImageField``
|
``ImageField``
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Like ``FileField``, but validates that the uploaded object is a valid
|
Like `FileField`_, but validates that the uploaded object is a valid
|
||||||
image. Has two extra optional arguments, ``height_field`` and
|
image. Has two extra optional arguments, ``height_field`` and
|
||||||
``width_field``, which, if set, will be auto-populated with the height and
|
``width_field``, which, if set, will be auto-populated with the height and
|
||||||
width of the image each time a model instance is saved.
|
width of the image each time a model instance is saved.
|
||||||
|
@ -1557,7 +1557,7 @@ as a custom extension to the ``TextInput`` widget::
|
|||||||
class CommentWidget(forms.TextInput):
|
class CommentWidget(forms.TextInput):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs.setdefault('attrs',{}).update({'size': '40'})
|
kwargs.setdefault('attrs',{}).update({'size': '40'})
|
||||||
super(forms.TextInput, self).__init__(*args, **kwargs)
|
super(CommentWidget, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
Then you can use this widget in your forms::
|
Then you can use this widget in your forms::
|
||||||
|
|
||||||
@ -1934,6 +1934,42 @@ will raise ``ValueError`` if the data doesn't validate.
|
|||||||
``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
|
``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
|
||||||
arguments that behave the same way as they do for ``form_for_model()``.
|
arguments that behave the same way as they do for ``form_for_model()``.
|
||||||
|
|
||||||
|
Let's modify the earlier `contact form`_ view example a little bit. Suppose we
|
||||||
|
have a ``Message`` model that holds each contact submission. Something like::
|
||||||
|
|
||||||
|
class Message(models.Model):
|
||||||
|
subject = models.CharField(max_length=100)
|
||||||
|
message = models.TextField()
|
||||||
|
sender = models.EmailField()
|
||||||
|
cc_myself = models.BooleanField()
|
||||||
|
|
||||||
|
You could use this model to create a form (using ``form_for_model()``). You
|
||||||
|
could also use existing ``Message`` instances to create a form for editing
|
||||||
|
messages. The earlier_ view can be changed slightly to accept the ``id`` value
|
||||||
|
of an existing ``Message`` and present it for editing::
|
||||||
|
|
||||||
|
def contact_edit(request, msg_id):
|
||||||
|
# Create the form from the message id.
|
||||||
|
message = get_object_or_404(Message, id=msg_id)
|
||||||
|
ContactForm = form_for_instance(message)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = ContactForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
return HttpResponseRedirect('/url/on_success/')
|
||||||
|
else:
|
||||||
|
form = ContactForm()
|
||||||
|
return render_to_response('contact.html', {'form': form})
|
||||||
|
|
||||||
|
Aside from how we create the ``ContactForm`` class here, the main point to
|
||||||
|
note is that the form display in the ``GET`` branch of the function
|
||||||
|
will use the values from the ``message`` instance as initial values for the
|
||||||
|
form field.
|
||||||
|
|
||||||
|
.. _contact form: `Simple view example`_
|
||||||
|
.. _earlier: `Simple view example`_
|
||||||
|
|
||||||
When should you use ``form_for_model()`` and ``form_for_instance()``?
|
When should you use ``form_for_model()`` and ``form_for_instance()``?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -1101,10 +1101,11 @@ To disable this behavior, just remove all entries from the ``ADMINS`` setting.
|
|||||||
404 errors
|
404 errors
|
||||||
----------
|
----------
|
||||||
|
|
||||||
When ``DEBUG`` is ``False`` and your ``MIDDLEWARE_CLASSES`` setting includes
|
When ``DEBUG`` is ``False``, ``SEND_BROKEN_LINK_EMAILS`` is ``True`` and your
|
||||||
``CommonMiddleware``, Django will e-mail the users listed in the ``MANAGERS``
|
``MIDDLEWARE_CLASSES`` setting includes ``CommonMiddleware``, Django will
|
||||||
setting whenever your code raises a 404 and the request has a referer.
|
e-mail the users listed in the ``MANAGERS`` setting whenever your code raises
|
||||||
(It doesn't bother to e-mail for 404s that don't have a referer.)
|
a 404 and the request has a referer. (It doesn't bother to e-mail for 404s
|
||||||
|
that don't have a referer.)
|
||||||
|
|
||||||
You can tell Django to stop reporting particular 404s by tweaking the
|
You can tell Django to stop reporting particular 404s by tweaking the
|
||||||
``IGNORABLE_404_ENDS`` and ``IGNORABLE_404_STARTS`` settings. Both should be a
|
``IGNORABLE_404_ENDS`` and ``IGNORABLE_404_STARTS`` settings. Both should be a
|
||||||
|
@ -473,7 +473,7 @@ Once you have a ``Client`` instance, you can call any of the following methods:
|
|||||||
data. For example::
|
data. For example::
|
||||||
|
|
||||||
>>> c = Client()
|
>>> c = Client()
|
||||||
>>> c.get('/login/', {'name': 'fred', 'passwd': 'secret'})
|
>>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'})
|
||||||
|
|
||||||
...will result in the evaluation of a POST request to this URL::
|
...will result in the evaluation of a POST request to this URL::
|
||||||
|
|
||||||
|
@ -259,6 +259,22 @@ These concepts are represented by simple Python classes. Edit the
|
|||||||
choice = models.CharField(max_length=200)
|
choice = models.CharField(max_length=200)
|
||||||
votes = models.IntegerField()
|
votes = models.IntegerField()
|
||||||
|
|
||||||
|
.. adminition:: Errors about ``max_length``
|
||||||
|
|
||||||
|
If Django gives you an error message saying that ``max_length`` is
|
||||||
|
not a valid argument, you're most likely using an old version of
|
||||||
|
Django. (This version of the tutorial is written for the latest
|
||||||
|
development version of Django.) If you're using a Subversion checkout
|
||||||
|
of Django's development version (see `the installation docs`_ for
|
||||||
|
more information), you shouldn't have any problems.
|
||||||
|
|
||||||
|
If you want to stick with an older version of Django, you'll want to
|
||||||
|
switch to `the Django 0.96 tutorial`_, because this tutorial covers
|
||||||
|
several features that only exist in the Django development version.
|
||||||
|
|
||||||
|
.. _the installation docs: ../install/
|
||||||
|
.. _the Django 0.96 tutorial: ../0.96/tutorial01/
|
||||||
|
|
||||||
The code is straightforward. Each model is represented by a class that
|
The code is straightforward. Each model is represented by a class that
|
||||||
subclasses ``django.db.models.Model``. Each model has a number of class
|
subclasses ``django.db.models.Model``. Each model has a number of class
|
||||||
variables, each of which represents a database field in the model.
|
variables, each of which represents a database field in the model.
|
||||||
@ -487,6 +503,23 @@ the ``polls/models.py`` file) and adding a ``__unicode__()`` method to both
|
|||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.choice
|
return self.choice
|
||||||
|
|
||||||
|
.. admonition:: If ``__unicode__()`` doesn't seem to work
|
||||||
|
|
||||||
|
If you add the ``__unicode__()`` method to your models and don't
|
||||||
|
see any change in how they're represented, you're most likely using
|
||||||
|
an old version of Django. (This version of the tutorial is written
|
||||||
|
for the latest development version of Django.) If you're using a
|
||||||
|
Subversion checkout of of Django's development version (see `the
|
||||||
|
installation docs`_ for more information), you shouldn't have any
|
||||||
|
problems.
|
||||||
|
|
||||||
|
If you want to stick with an older version of Django, you'll want to
|
||||||
|
switch to `the Django 0.96 tutorial`_, because this tutorial covers
|
||||||
|
several features that only exist in the Django development version.
|
||||||
|
|
||||||
|
.. _the installation docs: ../install/
|
||||||
|
.. _the Django 0.96 tutorial: ../0.96/tutorial01/
|
||||||
|
|
||||||
It's important to add ``__unicode__()`` methods to your models, not only for
|
It's important to add ``__unicode__()`` methods to your models, not only for
|
||||||
your own sanity when dealing with the interactive prompt, but also because
|
your own sanity when dealing with the interactive prompt, but also because
|
||||||
objects' representations are used throughout Django's automatically-generated
|
objects' representations are used throughout Django's automatically-generated
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
from datetime import timedelta, date
|
||||||
from django.template import Template, Context, add_to_builtins
|
from django.template import Template, Context, add_to_builtins
|
||||||
|
from django.utils.dateformat import DateFormat
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
add_to_builtins('django.contrib.humanize.templatetags.humanize')
|
add_to_builtins('django.contrib.humanize.templatetags.humanize')
|
||||||
|
|
||||||
@ -8,13 +11,12 @@ class HumanizeTests(unittest.TestCase):
|
|||||||
def humanize_tester(self, test_list, result_list, method):
|
def humanize_tester(self, test_list, result_list, method):
|
||||||
# Using max below ensures we go through both lists
|
# Using max below ensures we go through both lists
|
||||||
# However, if the lists are not equal length, this raises an exception
|
# However, if the lists are not equal length, this raises an exception
|
||||||
for index in xrange(len(max(test_list,result_list))):
|
for index in xrange(max(len(test_list), len(result_list))):
|
||||||
test_content = test_list[index]
|
test_content = test_list[index]
|
||||||
t = Template('{{ test_content|%s }}' % method)
|
t = Template('{{ test_content|%s }}' % method)
|
||||||
rendered = t.render(Context(locals())).strip()
|
rendered = t.render(Context(locals())).strip()
|
||||||
self.assertEqual(rendered, result_list[index],
|
self.assertEqual(rendered, result_list[index],
|
||||||
msg="""%s test failed, produced %s,
|
msg="%s test failed, produced %s, should've produced %s" % (method, rendered, result_list[index]))
|
||||||
should've produced %s""" % (method, rendered, result_list[index]))
|
|
||||||
|
|
||||||
def test_ordinal(self):
|
def test_ordinal(self):
|
||||||
test_list = ('1','2','3','4','11','12',
|
test_list = ('1','2','3','4','11','12',
|
||||||
@ -49,6 +51,20 @@ should've produced %s""" % (method, rendered, result_list[index]))
|
|||||||
|
|
||||||
self.humanize_tester(test_list, result_list, 'apnumber')
|
self.humanize_tester(test_list, result_list, 'apnumber')
|
||||||
|
|
||||||
|
def test_naturalday(self):
|
||||||
|
from django.template import defaultfilters
|
||||||
|
today = date.today()
|
||||||
|
yesterday = today - timedelta(days=1)
|
||||||
|
tomorrow = today + timedelta(days=1)
|
||||||
|
someday = today - timedelta(days=10)
|
||||||
|
notdate = u"I'm not a date value"
|
||||||
|
|
||||||
|
test_list = (today, yesterday, tomorrow, someday, notdate)
|
||||||
|
someday_result = defaultfilters.date(someday)
|
||||||
|
result_list = (_(u'today'), _(u'yesterday'), _(u'tomorrow'),
|
||||||
|
someday_result, u"I'm not a date value")
|
||||||
|
self.humanize_tester(test_list, result_list, 'naturalday')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user