Added a rough draft of the 1.0 porting guide, and an obviously incomplete placeholder for the 1.0 release notes. Thanks to daonb, patrickf, and ramiro for contributions to this porting guide. Refs #8438.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8856 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
79d2ee3b6d
commit
1156db790a
|
@ -632,6 +632,8 @@ It is important you use a ``ModelForm`` here otherwise things can break. See the
|
|||
:ref:`forms <ref-forms-index>` documentation on :ref:`custom validation
|
||||
<ref-forms-validation>` for more information.
|
||||
|
||||
.. _admin-inlines:
|
||||
|
||||
``InlineModelAdmin`` objects
|
||||
============================
|
||||
|
||||
|
|
|
@ -0,0 +1,691 @@
|
|||
=========================================
|
||||
Porting your apps from Django 0.96 to 1.0
|
||||
=========================================
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
Django 1.0 breaks compatibility with 0.96 in some areas.
|
||||
|
||||
This guide will help you port 0.96 projects and apps to 1.0. The first part of
|
||||
this document includes the common changes needed to run with 1.0. If after going
|
||||
through the first part your code still breaks, check the section `Less-common
|
||||
Changes`_ for a list of a bunch of less-common compatibility issues.
|
||||
|
||||
.. seealso::
|
||||
|
||||
The :ref:`1.0 release notes <releases-1.0>`. That document explains the new
|
||||
features in 1.0 more deeply; the porting guide is more concerned with
|
||||
helping you quickly update your code.
|
||||
|
||||
Common changes
|
||||
==============
|
||||
|
||||
This section describes the changes between 0.96 and 1.0 that most users will
|
||||
need to make.
|
||||
|
||||
Use Unicode
|
||||
-----------
|
||||
|
||||
Change string literals (``'foo'``) into Unicode literals (``u'foo'``). Django
|
||||
now uses Unicode strings throughout. In most places, raw strings will continue
|
||||
to work, but updating to use Unicode literals will prevent some obscure
|
||||
problems.
|
||||
|
||||
See :ref:`ref-unicode` for full details.
|
||||
|
||||
Models
|
||||
------
|
||||
|
||||
Common changes to your models file:
|
||||
|
||||
Rename ``maxlength`` to ``max_length``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Rename your ``maxlength`` argument to ``max_length`` (this was changed to be
|
||||
consistant with form fields):
|
||||
|
||||
Replace ``__str__`` with ``__unicode__``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Replace your model's ``__str__`` function with a ``__unicode__`` method, and
|
||||
make sure you `use Unicode`_ (``u'foo'``) in that method.
|
||||
|
||||
Remove ``prepopulated_from``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Remove the ``prepopulated_from`` argument on model fields. It's no longer valid
|
||||
and has been moved to the ``AdminModel`` class in ``admin.py``. See `the
|
||||
admin`_, below, for more details about changes to the admin.
|
||||
|
||||
Replace ``class Admin:`` with ``admin.py``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Remove all your inner ``class Admin`` declarations from your models. They won't
|
||||
break anything if you leave them, but they also won't do anything. To register
|
||||
apps with the admin you'll move those declarations to an ``admin.py`` file;
|
||||
see `the admin`_ below for more details.
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
Below is an example ``models.py`` file with all the changes you'll need to make:
|
||||
|
||||
Old (0.96) ``models.py``::
|
||||
|
||||
class Author(models.Model):
|
||||
first_name = models.CharField(maxlength=30)
|
||||
last_name = models.CharField(maxlength=30)
|
||||
slug = models.CharField(maxlength=60, prepopulate_from=('first_name', 'last_name'))
|
||||
|
||||
class Admin:
|
||||
list_display = ['first_name', 'last_name']
|
||||
|
||||
New (1.0) ``models.py``::
|
||||
|
||||
class Author(models.Model):
|
||||
first_name = models.CharField(max_length=30)
|
||||
last_name = models.CharField(max_length=30)
|
||||
slug = models.CharField(max_length=60)
|
||||
|
||||
New (1.0) ``admin.py``::
|
||||
|
||||
from django.contrib import admin
|
||||
from models import Author
|
||||
|
||||
class AuthorAdmin(admin.ModelAdmin):
|
||||
list_display=['first_name', 'last_name']
|
||||
prepopulated_fields = {
|
||||
'slug': ('first_name', 'last_name')
|
||||
}
|
||||
|
||||
admin.site.register(Author, AuthorAdmin)
|
||||
|
||||
The Admin
|
||||
---------
|
||||
|
||||
One of the biggest changes in 1.0 is the new admin. The Django administrative
|
||||
interface (``django.contrib.admin``) has been completely refactored; admin
|
||||
definitions are now completely decoupled from model definitions, the framework
|
||||
as been rewritten to use Django's new form-handling library and redesigned with
|
||||
extensibility and customization in mind.
|
||||
|
||||
Practially, this means you'll need to rewrite all of your ``class Admin``
|
||||
declarations. You've already seen in `models`_ above how to replace your ``class
|
||||
Admin`` with a ``admin.site.register()`` call in an ``admin.py`` file. Below are
|
||||
some more details on how to rewrite that ``Admin`` declaration into the new
|
||||
syntax.
|
||||
|
||||
.. seealso::
|
||||
|
||||
A contributor to djangosnippets__ has written a script that'll `scan your
|
||||
models.py and generate a corresponding admin.py`__.
|
||||
|
||||
__ http://www.djangosnippets.org/
|
||||
__ http://www.djangosnippets.org/snippets/603/
|
||||
|
||||
Use new inline syntax
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The new ``edit_inline`` options have all been moved to ``admin.py``. Here's an
|
||||
example:
|
||||
|
||||
Old (0.96)::
|
||||
|
||||
class Parent(models.Model):
|
||||
...
|
||||
|
||||
class Child(models.Model):
|
||||
parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)
|
||||
|
||||
|
||||
New (1.0)::
|
||||
|
||||
class ChildInline(admin.StackedInline):
|
||||
model = Child
|
||||
extra = 3
|
||||
|
||||
class ParentAdmin(models.ModelAdmin):
|
||||
model = Parent
|
||||
inlines = [ChildInline]
|
||||
|
||||
admin.site.register(Parent, ParentAdmin)
|
||||
|
||||
See :ref:`admin-inlines` for more details.
|
||||
|
||||
Simplify `fields``, or use ``fieldsets``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The old ``fields`` syntax was quite confusing, and has been simplified. The old
|
||||
syntax still works, but you'll need to use ``fieldsets`` instead.
|
||||
|
||||
Old (0.96)::
|
||||
|
||||
class ModelOne(models.Model):
|
||||
...
|
||||
|
||||
class Admin:
|
||||
fields = (
|
||||
(None, {'fields': ('foo','bar')}),
|
||||
)
|
||||
|
||||
class ModelTwo(models.Model):
|
||||
...
|
||||
|
||||
class Admin:
|
||||
fields = (
|
||||
('group1', {'fields': ('foo','bar'), 'classes': 'collapse'}),
|
||||
('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}),
|
||||
)
|
||||
|
||||
|
||||
New (1.0)::
|
||||
|
||||
class ModelOneAdmin(admin.ModelAdmin):
|
||||
fields = ('foo', 'bar')
|
||||
|
||||
class ModelTwoAdmin(admin.ModelAdmin):
|
||||
fieldsets = (
|
||||
('group1', {'fields': ('foo','bar'), 'classes': 'collapse'}),
|
||||
('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}),
|
||||
)
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
* More detailed information about the changes and the reasons behind them
|
||||
can be found on the `NewformsAdminBranch wiki page`__
|
||||
|
||||
* The new admin comes with a ton of new features; you can read about them in
|
||||
the :ref:`admin documentation <ref-contrib-admin>`.
|
||||
|
||||
__ http://code.djangoproject.com/wiki/NewformsAdminBranch
|
||||
|
||||
URLS
|
||||
----
|
||||
|
||||
Update your root ``urls.py``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you are using the admin site you need to update your root ``urls.py``.
|
||||
|
||||
Old (0.96) ``urls.py``::
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^admin/', include('django.contrib.admin.urls')),
|
||||
|
||||
# ... the rest of your URLs here ...
|
||||
)
|
||||
|
||||
New (1.0) ``urls.py``::
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
# The next two lines enable the admin and load each admin.py file:
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^admin/(.*)', admin.site.root),
|
||||
|
||||
# ... the rest of your URLs here ...
|
||||
)
|
||||
|
||||
Views
|
||||
-----
|
||||
|
||||
Use ``django.forms`` instead of ``newforms``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Replace ``django.newforms`` with ``django.forms`` -- Django 1.0 renamed the
|
||||
``newforms`` module (introduced in 0.96) to plain old ``forms``. The
|
||||
``oldforms`` module was also removed removed.
|
||||
|
||||
If you are already using new forms all you have to do is change your import
|
||||
statement. Instead of ``from django import newforms as forms``, use ``from
|
||||
django import forms``.
|
||||
|
||||
If you are using the old forms system, you will have to rewrite your forms. A
|
||||
good place to start is the :ref:`forms documentation <topics-forms-index>`
|
||||
|
||||
Handle uploaded files using the new API
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Replace use of uploaded files -- that is, entries in ``request.FILES`` -- as
|
||||
simple dictionaries with the new :class:`~django.core.files.UploadedFile`. The
|
||||
old dictionary syntax no longer works.
|
||||
|
||||
Thus, in a view like::
|
||||
|
||||
def my_view(request):
|
||||
f = request.FILES['file_field_name']
|
||||
...
|
||||
|
||||
You'd need to make the following changes:
|
||||
|
||||
===================== =====================
|
||||
Old (0.96) New (1.0)
|
||||
===================== =====================
|
||||
``f['content']`` ``f.read()``
|
||||
``f['filename']`` ``f.name``
|
||||
``f['content-type']`` ``f.content_type``
|
||||
===================== =====================
|
||||
|
||||
Templates
|
||||
---------
|
||||
|
||||
Learn to love autoescaping
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, the templating system now automatically HTML-escapes the output of
|
||||
every variable. To learn more, see :ref:`automatic-html-escaping`.
|
||||
|
||||
To disable auto-escaping for an individual variable, use the :tfilter:`safe`
|
||||
filter:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
This will be escaped: {{ data }}
|
||||
This will not be escaped: {{ data|safe }}
|
||||
|
||||
To disable auto-escaping for an entire template, wrap the template (or just a
|
||||
particular section of the template) in the :ttag:`autoescape` tag:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% autoescape off %}
|
||||
... unescaped template content here ...
|
||||
{% endautoescape %}
|
||||
|
||||
Less-common changes
|
||||
===================
|
||||
|
||||
The following changes are smaller, more localized changes. They should only
|
||||
affect more advanced users, but it's probably worth reading through the list and
|
||||
checking your code for these things.
|
||||
|
||||
Signals
|
||||
-------
|
||||
|
||||
* Add ``**kwargs`` to any registered signal handlers.
|
||||
|
||||
* Connect, disconnect, and send signals via methods on the
|
||||
:class:`~django.dispatch.Signal` object instead of through module methods in
|
||||
``django.dispatch.dispatcher``.
|
||||
|
||||
* Remove any use of the ``Anonymous`` and ``Any`` sender options; they no longer
|
||||
exist. You can still receive signals sent by any sender by using
|
||||
``sender=None``
|
||||
|
||||
* Make any custom signals you've declared into instances of
|
||||
:class:`django.dispatch.Signal`` instead of anonymous objects.
|
||||
|
||||
Here's quick summary of the code changes you'll need to make:
|
||||
|
||||
================================================= ======================================
|
||||
Old (0.96) New (1.0)
|
||||
================================================= ======================================
|
||||
``def callback(sender)`` ``def callback(sender, **kwargs)``
|
||||
``sig = object()`` ``sig = django.dispatch.Signal()``
|
||||
``dispatcher.connect(callback, sig)`` ``sig.connect(callback)``
|
||||
``dispatcher.send(sig, sender)`` ``sig.send(sender)``
|
||||
``dispatcher.connect(callback, sig, sender=Any)`` ``sig.connect(callback, sender=None)``
|
||||
================================================= ======================================
|
||||
|
||||
Template tags
|
||||
-------------
|
||||
|
||||
:ttag:`spaceless` tag
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The spaceless template tag removes *all* spaces between HTML tags instead of
|
||||
preserving a single space.
|
||||
|
||||
Localflavor
|
||||
-----------
|
||||
|
||||
US localflavor
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
``django.contrib.localflavor.usa`` has been renamed
|
||||
:mod:`django.contribg.localflavor.us`. This change was made to match the naming
|
||||
scheme of other local flavors.
|
||||
|
||||
Sessions
|
||||
--------
|
||||
|
||||
Getting a new session key
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``SeesionBase.get_new_session_key()`` has been renamed to
|
||||
``_get_new_session_key()``; ``get_new_session_object()`` no longer exists.
|
||||
|
||||
Fixtures
|
||||
--------
|
||||
|
||||
Loading a row no longer calls ``save()``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Previously, loading a row automatically ran the model's ``save()`` method. This
|
||||
is no longer the case, so any fields (for example: timestamps) that were
|
||||
auto-populated by a ``save()`` now need explicit values in any fixture.
|
||||
|
||||
Settings
|
||||
--------
|
||||
|
||||
Better exceptions
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The old :exc:`EnvironmentError` was split into an :exc:`ImportError` raised when
|
||||
Django fails to find the settings module and a :exc:`RuntimeError` when you try
|
||||
to reconfigure settings after having already used them
|
||||
|
||||
``LOGIN_URL`` has moved
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``LOGIN_URL`` constant moved from ``django.contrib.auth`` into the
|
||||
``settings`` module. Instead of using ``from django.contrib.auth import
|
||||
LOGIN_URL`` refer to :setting:`settings.LOGIN_URL <LOGIN_URL>`.
|
||||
|
||||
:setting:`APPEND_SLASH` behaviour has been updated
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In 0.96, if a URL didn't end in a slash or have a period in the final
|
||||
component of it's path, and ``APPEND_SLASH`` was True, Django would redirect
|
||||
to the same URL, but with a slash appended to the end. Now, Django checks to
|
||||
see if the pattern without the trailing slash would be matched by something in
|
||||
your URL patterns. If so, no redirection takes place, because it is assumed
|
||||
you deliberately wanted to catch that pattern.
|
||||
|
||||
For most people, this won't require any changes. Some people, though, have URL
|
||||
patterns that look like this::
|
||||
|
||||
r'/some_prefix/(.*)$'
|
||||
|
||||
Previously, those patterns would have been redirected to have a trailing
|
||||
slash. If you always want a slash on such URLs, rewrite the pattern as::
|
||||
|
||||
r'/some_prefix/(.*/)$'
|
||||
|
||||
Samller model changes
|
||||
---------------------
|
||||
|
||||
Different exception from ``get()``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The models manager now returns a :exc:`MultipleObjectsReturned` exception
|
||||
instead of :exc:`AssertionError`:
|
||||
|
||||
Old (0.96)::
|
||||
|
||||
try:
|
||||
Model.objects.get(...)
|
||||
except AssertionError:
|
||||
handle_the_error()
|
||||
|
||||
New (1.0)::
|
||||
|
||||
try:
|
||||
Model.objects.get(...)
|
||||
except Model.MultipleObjectsReturned:
|
||||
handle_the_error()
|
||||
|
||||
``LazyDate`` has been fired
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``LazyDate`` helper class no longer exists.
|
||||
|
||||
Default field values and query arguments can both be callable objects, so
|
||||
instances of ``LazyDate`` can be replaced with a reference to ``datetime.datetime.now``:
|
||||
|
||||
Old (0.96)::
|
||||
|
||||
class Article(models.Model):
|
||||
title = models.CharField(maxlength=100)
|
||||
published = models.DateField(default=LazyDate())
|
||||
|
||||
New (1.0)::
|
||||
|
||||
import datetime
|
||||
|
||||
class Article(models.Model):
|
||||
title = models.CharField(maxlength=100)
|
||||
published = models.DateField(default=datetime.datetime.now)
|
||||
|
||||
``DecimalField`` is new, and ``FloatField`` is now a proper float
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Old (0.96)::
|
||||
|
||||
class MyModel(models.Model):
|
||||
field_name = models.FloatField(max_digits=10, decimal_places=3)
|
||||
...
|
||||
|
||||
New (1.0)::
|
||||
|
||||
class MyModel(models.Model):
|
||||
field_name = models.DecimalField(max_digits=10, decimal_places=3)
|
||||
...
|
||||
|
||||
If you forget to make this change, you will see errors about ``FloatField``
|
||||
not taking a ``max_digits`` attribute in ``__init__``, since the new
|
||||
``FloatField`` takes no precision-related arguments.
|
||||
|
||||
If you are using MySQL or PostgreSQL, there are no further changes needed. The
|
||||
database column types for ``DecimalField`` are the same as for the old
|
||||
``FloatField``.
|
||||
|
||||
If you are using SQLite, you need to force the database to view the
|
||||
appropriate columns as decimal types, rather than floats. To do this, you'll
|
||||
need to reload your data. Do this after you have made the change to using
|
||||
``DecimalField`` in your code and updated the Django code.
|
||||
|
||||
.. warning::
|
||||
|
||||
**Back up your database first!**
|
||||
|
||||
For SQLite, this means making a copy of the single file that stores the
|
||||
database (the name of that file is the ``DATABASE_NAME`` in your settings.py
|
||||
file).
|
||||
|
||||
To upgrade each application to use a ``DecimalField``, do the following,
|
||||
replacing ``<app>`` in the code below with each app's name:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
|
||||
$ ./manage.py reset <app>
|
||||
$ ./manage.py loaddata data-dump.xml
|
||||
|
||||
Notes:
|
||||
|
||||
1. It is important that you remember to use XML format in the first step of
|
||||
this process. We are exploiting a feature of the XML data dumps that makes
|
||||
porting floats to decimals with SQLite possible.
|
||||
|
||||
2. In the second step you will be asked to confirm that you are prepared to
|
||||
lose the data for the application(s) in question. Say yes; we'll restore
|
||||
this data in the third step, of course.
|
||||
|
||||
3. ``DecimalField`` is not used in any of the apps shipped with Django prior
|
||||
to this change being made, so you do not need to worry about performing
|
||||
this procedure for any of the standard Django models.
|
||||
|
||||
If something goes wrong in the above process, just copy your backed up
|
||||
database file over the top of the original file and start again.
|
||||
|
||||
Internationalization
|
||||
--------------------
|
||||
|
||||
:func:`django.views.i18n.set_language` now requires a POST request
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Previously, a GET request was used. The old behavior meant that state (the
|
||||
locale used to display the site) could be changed by a GET request, which is
|
||||
against the HTTP specification's recommendations. Code calling this view must
|
||||
ensure that a POST request is now made, instead of a GET. This means you can
|
||||
no longer use a link to access the view, but must use a form submission of
|
||||
some kind (e.g. a button).
|
||||
|
||||
``_()`` is no longer in builtins
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``_()`` is no longer monkeypatched into builtins. If you were previously
|
||||
relying on ``_()`` always being present, you should now explicitly import
|
||||
``ugettext`` or ``ugettext_lazy``, if appropriate, and alias it to ``_``
|
||||
yourself::
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
HTTP request/response objects
|
||||
-----------------------------
|
||||
|
||||
Accessing ``HTTPResponse`` headers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``django.http.HttpResponse.headers`` has been renamed to ``_headers`` and
|
||||
:class:`HttpResponse`` now supports containment checking directly. So use
|
||||
``if header in response:`` instead of ``if header in response.headers:``.
|
||||
|
||||
Generic relations
|
||||
-----------------
|
||||
|
||||
Generic relations have been moved out of core
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The generic relation classes -- ``GenericForeignKey`` and ``GenericRelation``
|
||||
-- have moved into the :mod:`django.contrib.contenttypes` module.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
:meth:`django.test.Client.login` has changed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Old (0.96)::
|
||||
|
||||
from django.test import Client
|
||||
c = Client()
|
||||
c.login('/path/to/login','myuser','mypassword')
|
||||
|
||||
New (1.0)::
|
||||
|
||||
# ... same as above, but then:
|
||||
c.login(username='myuser', password='mypassword')
|
||||
|
||||
Management commands
|
||||
-------------------
|
||||
|
||||
Running management commands from your code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:mod:`django.core.management`` has been greately refactored.
|
||||
|
||||
Calls to management services in your code will now need to use
|
||||
``call_command``. For example, if you have some test code that calls flush and
|
||||
load_data::
|
||||
|
||||
from django.core import management
|
||||
management.flush(verbosity=0, interactive=False)
|
||||
management.load_data(['test_data'], verbosity=0)
|
||||
|
||||
You will need to change this code to read::
|
||||
|
||||
from django.core import management
|
||||
management.call_command('flush', verbosity=0, interactive=False)
|
||||
management.call_command('loaddata', 'test_data', verbosity=0)
|
||||
|
||||
Subcommands must now preceed options
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``django-admin.py`` and ``manage.py`` now require subcommands to precede
|
||||
options. So:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ django-admin.py --settings=foo.bar runserver
|
||||
|
||||
no longer works, and must be changed to:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ django-admin.py runserver --settings=foo.bar
|
||||
|
||||
Syndication
|
||||
-----------
|
||||
|
||||
``Feed.__init__`` has changed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``__init__()`` parameters in in syndication framework's ``Feed`` class now
|
||||
take an ``HttpRequest`` object as its second parameter, instead of the feed's
|
||||
URL. This allows the syndication framework to work without requiring the sites
|
||||
framework. This only affects code that subclass ``Feed`` and overrides the
|
||||
``__init__()`` method, and code that calls ``Feed.__init__()`` directly.
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
``SortedDictFromList`` is gone
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`django.newforms.forms.SortedDictFromList`` was removed.
|
||||
:class:`django.utils.datastructures.SortedDict`` can now be instantiated with
|
||||
a sequence of tuples.
|
||||
|
||||
To update your code:
|
||||
|
||||
1. Use :class:`django.utils.datastructures.SortedDict` wherever you were
|
||||
using ``django.newforms.forms.SortedDictFromList``.
|
||||
|
||||
2. Since :meth:`django.utils.datastructures.SortedDict.copy` return a
|
||||
deepcopy as ``SortedDictFromList`` method did, you will need to update
|
||||
your code if you were relying on a deepcopy. Do this by using
|
||||
``copy.deepcopy`` directly.
|
||||
|
||||
Database backend functions
|
||||
--------------------------
|
||||
|
||||
Database backend functions have been renamed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Almost *all* of the database backend-level functions have been renamed and/or
|
||||
relocated. None of these were documented, but you'll need to change your code
|
||||
if you're using any of these functions, all of which are in :mod:`django.db`:
|
||||
|
||||
======================================= ===================================================
|
||||
Old (0.96) New (1.0)
|
||||
======================================= ===================================================
|
||||
``backend.get_autoinc_sql`` ``connection.ops.autoinc_sql``
|
||||
``backend.get_date_extract_sql`` ``connection.ops.date_extract_sql``
|
||||
``backend.get_date_trunc_sql`` ``connection.ops.date_trunc_sql``
|
||||
``backend.get_datetime_cast_sql`` ``connection.ops.datetime_cast_sql``
|
||||
``backend.get_deferrable_sql`` ``connection.ops.deferrable_sql``
|
||||
``backend.get_drop_foreignkey_sql`` ``connection.ops.drop_foreignkey_sql``
|
||||
``backend.get_fulltext_search_sql`` ``connection.ops.fulltext_search_sql``
|
||||
``backend.get_last_insert_id`` ``connection.ops.last_insert_id``
|
||||
``backend.get_limit_offset_sql`` ``connection.ops.limit_offset_sql``
|
||||
``backend.get_max_name_length`` ``connection.ops.max_name_length``
|
||||
``backend.get_pk_default_value`` ``connection.ops.pk_default_value``
|
||||
``backend.get_random_function_sql`` ``connection.ops.random_function_sql``
|
||||
``backend.get_sql_flush`` ``connection.ops.sql_flush``
|
||||
``backend.get_sql_sequence_reset`` ``connection.ops.sequence_reset_sql``
|
||||
``backend.get_start_transaction_sql`` ``connection.ops.start_transaction_sql``
|
||||
``backend.get_tablespace_sql`` ``connection.ops.tablespace_sql``
|
||||
``backend.quote_name`` ``connection.ops.quote_name``
|
||||
``backend.get_query_set_class`` ``connection.ops.query_set_class``
|
||||
``backend.get_field_cast_sql`` ``connection.ops.field_cast_sql``
|
||||
``backend.get_drop_sequence`` ``connection.ops.drop_sequence_sql``
|
||||
``backend.OPERATOR_MAPPING`` ``connection.operators``
|
||||
``backend.allows_group_by_ordinal`` ``connection.features.allows_group_by_ordinal``
|
||||
``backend.allows_unique_and_pk`` ``connection.features.allows_unique_and_pk``
|
||||
``backend.autoindexes_primary_keys`` ``connection.features.autoindexes_primary_keys``
|
||||
``backend.needs_datetime_string_cast`` ``connection.features.needs_datetime_string_cast``
|
||||
``backend.needs_upper_for_iops`` ``connection.features.needs_upper_for_iops``
|
||||
``backend.supports_constraints`` ``connection.features.supports_constraints``
|
||||
``backend.supports_tablespaces`` ``connection.features.supports_tablespaces``
|
||||
``backend.uses_case_insensitive_names`` ``connection.features.uses_case_insensitive_names``
|
||||
``backend.uses_custom_queryset`` ``connection.features.uses_custom_queryset``
|
||||
======================================= ===================================================
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
.. _releases-1.0:
|
||||
|
||||
========================
|
||||
Django 1.0 release notes
|
||||
========================
|
||||
|
||||
Welcome to Django 1.0!
|
||||
|
||||
Porting guide
|
||||
-------------
|
||||
|
||||
You can find detailed instructions on porting apps from Django 0.96 to Django
|
||||
1.0 in our porting guide:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
1.0-porting-guide
|
||||
|
|
@ -16,6 +16,7 @@ changes made in that version.
|
|||
1.0-alpha-2
|
||||
1.0-beta
|
||||
1.0-beta-2
|
||||
1.0
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
|
Loading…
Reference in New Issue