1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

gis: Merged revisions 6000-6020 via svnmerge from [repos:django/trunk trunk].

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6021 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2007-08-26 17:47:34 +00:00
parent 2052b508eb
commit cb64f5375c
22 changed files with 227 additions and 79 deletions

View File

@ -94,6 +94,7 @@ answer newbie questions, and generally made Django that much better:
Alex Dedul
deric@monowerks.com
Max Derkachev <mderk@yandex.ru>
Sander Dijkhuis <sander.dijkhuis@gmail.com>
Jordan Dimov <s3x3y1@gmail.com>
dne@mayonnaise.net
Maximillian Dornseif <md@hudora.de>

View File

@ -6,7 +6,7 @@ var SelectBox = {
SelectBox.cache[id] = new Array();
var cache = SelectBox.cache[id];
for (var i = 0; (node = box.options[i]); i++) {
cache.push({ value: node.value, text: node.text, displayed: 1 });
cache.push({value: node.value, text: node.text, displayed: 1});
}
},
redisplay: function(id) {
@ -50,7 +50,7 @@ var SelectBox = {
SelectBox.cache[id].length--;
},
add_to_cache: function(id, option) {
SelectBox.cache[id].push({ value: option.value, text: option.text, displayed: 1 });
SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1});
},
cache_contains: function(id, value) {
// Check if an item is contained in the cache
@ -68,7 +68,7 @@ var SelectBox = {
var option;
for (var i = 0; (option = from_box.options[i]); i++) {
if (option.selected && SelectBox.cache_contains(from, option.value)) {
SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1 });
SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
SelectBox.delete_from_cache(from, option.value);
}
}
@ -80,8 +80,10 @@ var SelectBox = {
var to_box = document.getElementById(to);
var option;
for (var i = 0; (option = from_box.options[i]); i++) {
SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1 });
SelectBox.delete_from_cache(from, option.value);
if (SelectBox.cache_contains(from, option.value)) {
SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
SelectBox.delete_from_cache(from, option.value);
}
}
SelectBox.redisplay(from);
SelectBox.redisplay(to);

View File

@ -17,7 +17,7 @@ def login(request, template_name='registration/login.html'):
errors = manipulator.get_validation_errors(request.POST)
if not errors:
# 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
redirect_to = settings.LOGIN_REDIRECT_URL
from django.contrib.auth import login

View File

@ -51,7 +51,6 @@ class SpatialRefSysTest(unittest.TestCase):
def test03_ellipsoid(self):
"Testing the ellipsoid property."
return
for sd in test_srs:
# Getting the ellipsoid and precision parameters.
ellps1 = sd['ellipsoid']

View File

@ -24,7 +24,7 @@ class Command(NoArgsCommand):
except ImportError:
pass
sql_list = sql_flush(self.style)
sql_list = sql_flush(self.style, only_django=True)
if interactive:
confirm = raw_input("""You have requested a flush of the database.

View File

@ -30,7 +30,7 @@ class Command(BaseCommand):
raise CommandError("%r is not a valid port number." % port)
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', '')
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 "Quit the server with %s." % quit_command
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)
run(addr, int(port), handler)
except WSGIServerException, e:

View File

@ -7,4 +7,4 @@ class Command(NoArgsCommand):
def handle_noargs(self, **options):
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))

View File

@ -13,6 +13,25 @@ def table_list():
cursor = connection.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):
"Returns a set of all models that are installed, given a list of existing table names."
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."
return sql_delete(app, style) + sql_all(app, style)
def sql_flush(style):
"Returns a list of the SQL statements used to flush the database."
def sql_flush(style, only_django=False):
"""
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
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
def sql_custom(app, style):

View File

@ -8,6 +8,7 @@ ImproperlyConfigured.
"""
from django.core.exceptions import ImproperlyConfigured
from django.db.backends import BaseDatabaseFeatures, BaseDatabaseOperations
def complain(*args, **kwargs):
raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet."
@ -21,13 +22,12 @@ class DatabaseError(Exception):
class IntegrityError(DatabaseError):
pass
class ComplainOnGetattr(object):
def __getattr__(self, *args, **kwargs):
complain()
class DatabaseOperations(BaseDatabaseOperations):
quote_name = complain
class DatabaseWrapper(object):
features = ComplainOnGetattr()
ops = ComplainOnGetattr()
features = BaseDatabaseFeatures()
ops = DatabaseOperations()
operators = {}
cursor = complain
_commit = complain

View File

@ -102,9 +102,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
cursor.execute("SET client_encoding to 'UNICODE'")
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
def typecast_string(s):

View File

@ -4,8 +4,17 @@ from django.db.backends import BaseDatabaseOperations
# used by both the 'postgresql' and 'postgresql_psycopg2' backends.
class DatabaseOperations(BaseDatabaseOperations):
def __init__(self, postgres_version=None):
self.postgres_version = postgres_version
def __init__(self):
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):
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
@ -52,28 +61,14 @@ class DatabaseOperations(BaseDatabaseOperations):
for sequence_info in sequences:
table_name = sequence_info['table']
column_name = sequence_info['column']
if column_name and len(column_name)>0:
# sequence name in this case will be <table>_<column>_seq
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')
)
)
if column_name and len(column_name) > 0:
sequence_name = '%s_%s_seq' % (table_name, column_name)
else:
# sequence name in this case will be <table>_id_seq
sql.append("%s %s %s %s %s %s;" % \
(style.SQL_KEYWORD('ALTER'),
style.SQL_KEYWORD('SEQUENCE'),
style.SQL_FIELD(self.quote_name('%s_id_seq' % table_name)),
style.SQL_KEYWORD('RESTART'),
style.SQL_KEYWORD('WITH'),
style.SQL_FIELD('1')
)
)
sequence_name = '%s_id_seq' % table_name
sql.append("%s setval('%s', 1, false);" % \
(style.SQL_KEYWORD('SELECT'),
style.SQL_FIELD(self.quote_name(sequence_name)))
)
return sql
else:
return []
@ -106,4 +101,4 @@ class DatabaseOperations(BaseDatabaseOperations):
style.SQL_KEYWORD('IS NOT'),
style.SQL_KEYWORD('FROM'),
style.SQL_TABLE(f.m2m_db_table())))
return output
return output

View File

@ -64,7 +64,4 @@ class DatabaseWrapper(BaseDatabaseWrapper):
cursor.tzinfo_factory = None
if set_tz:
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

View File

@ -355,8 +355,8 @@ def unordered_list(value):
Recursively takes a self-nested list and returns an HTML unordered list --
WITHOUT opening and closing <ul> tags.
The list is assumed to be in the proper format. For example, if ``var`` contains
``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
The list is assumed to be in the proper format. For example, if ``var``
contains: ``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``,
then ``{{ var|unordered_list }}`` would return::
<li>States
@ -371,14 +371,61 @@ def unordered_list(value):
</ul>
</li>
"""
def _helper(value, tabs):
def convert_old_style_list(list_):
"""
Converts old style lists to the new easier to understand format.
The old list format looked like:
['Item 1', [['Item 1.1', []], ['Item 1.2', []]]
And it is converted to:
['Item 1', ['Item 1.1', 'Item 1.2]]
"""
if not isinstance(list_, (tuple, list)) or len(list_) != 2:
return list_, False
first_item, second_item = list_
if second_item == []:
return [first_item], True
old_style_list = True
new_second_item = []
for sublist in second_item:
item, old_style_list = convert_old_style_list(sublist)
if not old_style_list:
break
new_second_item.extend(item)
if old_style_list:
second_item = new_second_item
return [first_item, second_item], old_style_list
def _helper(list_, tabs=1):
indent = u'\t' * tabs
if value[1]:
return u'%s<li>%s\n%s<ul>\n%s\n%s</ul>\n%s</li>' % (indent, force_unicode(value[0]), indent,
u'\n'.join([_helper(v, tabs+1) for v in value[1]]), indent, indent)
else:
return u'%s<li>%s</li>' % (indent, force_unicode(value[0]))
return _helper(value, 1)
output = []
list_length = len(list_)
i = 0
while i < list_length:
title = list_[i]
sublist = ''
sublist_item = None
if isinstance(title, (list, tuple)):
sublist_item = title
title = ''
elif i < list_length - 1:
next_item = list_[i+1]
if next_item and isinstance(next_item, (list, tuple)):
# The next item is a sub-list.
sublist_item = next_item
# We've processed the next item now too.
i += 1
if sublist_item:
sublist = _helper(sublist_item, tabs+1)
sublist = '\n%s<ul>\n%s\n%s</ul>\n%s' % (indent, sublist,
indent, indent)
output.append('%s<li>%s%s</li>' % (indent, force_unicode(title),
sublist))
i += 1
return '\n'.join(output)
value, converted = convert_old_style_list(value)
return _helper(value)
###################
# INTEGERS #

View File

@ -207,14 +207,23 @@ the database until you explicitly call ``save()``.
The ``save()`` method has no return value.
Updating ``ForeignKey`` fields works exactly the same way; simply assign an
object of the right type to the field in question::
Saving ForeignKey and ManyToManyField fields
--------------------------------------------
Updating ``ForeignKey`` fields works exactly the same way as saving a normal
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()
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.author = joe
entry.save()
entry.authors.add(joe)
Django will complain if you try to assign an object of the wrong type.
Django will complain if you try to assign or add an object of the wrong type.
How Django knows to UPDATE vs. INSERT
-------------------------------------

View File

@ -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``
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
---------
@ -240,6 +247,7 @@ Executes the equivalent of ``sqlreset`` for the given appnames.
runfcgi [options]
-----------------
Starts a set of FastCGI processes suitable for use with any web server
which supports the FastCGI protocol. See the `FastCGI deployment
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.
sqlclear [appname appname ...]
--------------------------------------
------------------------------
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.
sqlflush
--------
Prints the SQL statements that would be executed for the `flush`_ command.
sqlindexes [appname appname ...]
----------------------------------------
--------------------------------
Prints the CREATE INDEX SQL statements for the given appnames.
sqlreset [appname appname ...]
--------------------------------------
------------------------------
Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames.
sqlsequencereset [appname appname ...]
----------------------------------------------
--------------------------------------
Prints the SQL statements for resetting sequences for the given
appnames.
@ -466,6 +479,9 @@ This is useful in a number of ways:
Note that this server can only run on the default port on localhost; it does
not yet accept a ``host`` or ``port`` parameter.
Also note that it does *not* automatically detect changes to your Python source
code (as ``runserver`` does). It does, however, detect changes to templates.
.. _unit tests: ../testing/
validate

View File

@ -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
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)?
--------------------------------------------

View File

@ -344,7 +344,7 @@ development version. See the `Django 0.96 documentation`_ for the old behavior.
``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
``width_field``, which, if set, will be auto-populated with the height and
width of the image each time a model instance is saved.

View File

@ -1554,7 +1554,7 @@ as a custom extension to the ``TextInput`` widget::
class CommentWidget(forms.TextInput):
def __init__(self, *args, **kwargs):
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::

View File

@ -1101,10 +1101,11 @@ To disable this behavior, just remove all entries from the ``ADMINS`` setting.
404 errors
----------
When ``DEBUG`` is ``False`` and your ``MIDDLEWARE_CLASSES`` setting includes
``CommonMiddleware``, Django will e-mail the users listed in the ``MANAGERS``
setting whenever your code raises a 404 and the request has a referer.
(It doesn't bother to e-mail for 404s that don't have a referer.)
When ``DEBUG`` is ``False``, ``SEND_BROKEN_LINK_EMAILS`` is ``True`` and your
``MIDDLEWARE_CLASSES`` setting includes ``CommonMiddleware``, Django will
e-mail the users listed in the ``MANAGERS`` setting whenever your code raises
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
``IGNORABLE_404_ENDS`` and ``IGNORABLE_404_STARTS`` settings. Both should be a

View File

@ -1301,9 +1301,14 @@ unordered_list
Recursively takes a self-nested list and returns an HTML unordered list --
WITHOUT opening and closing <ul> tags.
**Changed in Django development version**
The format accepted by ``unordered_list`` has changed to an easier to
understand format.
The list is assumed to be in the proper format. For example, if ``var`` contains
``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
then ``{{ var|unordered_list }}`` would return::
``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, then
``{{ var|unordered_list }}`` would return::
<li>States
<ul>
@ -1317,6 +1322,9 @@ then ``{{ var|unordered_list }}`` would return::
</ul>
</li>
Note: the previous more restrictive and verbose format is still supported:
``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
upper
~~~~~

View File

@ -259,6 +259,22 @@ These concepts are represented by simple Python classes. Edit the
choice = models.CharField(max_length=200)
votes = models.IntegerField()
.. admonition:: 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
subclasses ``django.db.models.Model``. Each model has a number of class
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):
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
your own sanity when dealing with the interactive prompt, but also because
objects' representations are used throughout Django's automatically-generated

View File

@ -266,6 +266,22 @@ u'bc'
>>> slice_(u'abcdefg', u'0::2')
u'aceg'
>>> unordered_list([u'item 1', u'item 2'])
u'\t<li>item 1</li>\n\t<li>item 2</li>'
>>> unordered_list([u'item 1', [u'item 1.1']])
u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>'
>>> unordered_list([u'item 1', [u'item 1.1', u'item1.2'], u'item 2'])
u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item1.2</li>\n\t</ul>\n\t</li>\n\t<li>item 2</li>'
>>> unordered_list([u'item 1', [u'item 1.1', [u'item 1.1.1', [u'item 1.1.1.1']]]])
u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1\n\t\t<ul>\n\t\t\t<li>item 1.1.1\n\t\t\t<ul>\n\t\t\t\t<li>item 1.1.1.1</li>\n\t\t\t</ul>\n\t\t\t</li>\n\t\t</ul>\n\t\t</li>\n\t</ul>\n\t</li>'
>>> unordered_list(['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']])
u'\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>'
# Old format for unordered lists should still work
>>> unordered_list([u'item 1', []])
u'\t<li>item 1</li>'
@ -275,6 +291,9 @@ u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>'
>>> unordered_list([u'item 1', [[u'item 1.1', []], [u'item 1.2', []]]])
u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item 1.2</li>\n\t</ul>\n\t</li>'
>>> unordered_list(['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]])
u'\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>'
>>> add(u'1', u'2')
3