1. =========================================
    
  2. Porting your apps from Django 0.96 to 1.0
    
  3. =========================================
    
  4. 
    
  5. .. highlight:: python
    
  6. 
    
  7. Django 1.0 breaks compatibility with 0.96 in some areas.
    
  8. 
    
  9. This guide will help you port 0.96 projects and apps to 1.0. The first part of
    
  10. this document includes the common changes needed to run with 1.0. If after going
    
  11. through the first part your code still breaks, check the section `Less-common
    
  12. Changes`_ for a list of a bunch of less-common compatibility issues.
    
  13. 
    
  14. .. seealso::
    
  15. 
    
  16.     The :doc:`1.0 release notes </releases/1.0>`. That document explains the new
    
  17.     features in 1.0 more deeply; the porting guide is more concerned with
    
  18.     helping you quickly update your code.
    
  19. 
    
  20. Common changes
    
  21. ==============
    
  22. 
    
  23. This section describes the changes between 0.96 and 1.0 that most users will
    
  24. need to make.
    
  25. 
    
  26. Use Unicode
    
  27. -----------
    
  28. 
    
  29. Change string literals (``'foo'``) into Unicode literals (``u'foo'``). Django
    
  30. now uses Unicode strings throughout. In most places, raw strings will continue
    
  31. to work, but updating to use Unicode literals will prevent some obscure
    
  32. problems.
    
  33. 
    
  34. See :doc:`/ref/unicode` for full details.
    
  35. 
    
  36. Models
    
  37. ------
    
  38. 
    
  39. Common changes to your models file:
    
  40. 
    
  41. Rename ``maxlength`` to ``max_length``
    
  42. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  43. 
    
  44. Rename your ``maxlength`` argument to ``max_length`` (this was changed to be
    
  45. consistent with form fields):
    
  46. 
    
  47. Replace ``__str__`` with ``__unicode__``
    
  48. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  49. 
    
  50. Replace your model's ``__str__`` function with a ``__unicode__`` method, and
    
  51. make sure you `use Unicode`_ (``u'foo'``) in that method.
    
  52. 
    
  53. Remove ``prepopulated_from``
    
  54. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  55. 
    
  56. Remove the ``prepopulated_from`` argument on model fields. It's no longer valid
    
  57. and has been moved to the ``ModelAdmin`` class in ``admin.py``. See `the
    
  58. admin`_, below, for more details about changes to the admin.
    
  59. 
    
  60. Remove ``core``
    
  61. ~~~~~~~~~~~~~~~
    
  62. 
    
  63. Remove the ``core`` argument from your model fields. It is no longer
    
  64. necessary, since the equivalent functionality (part of :ref:`inline editing
    
  65. <admin-inlines>`) is handled differently by the admin interface now. You don't
    
  66. have to worry about inline editing until you get to `the admin`_ section,
    
  67. below. For now, remove all references to ``core``.
    
  68. 
    
  69. Replace ``class Admin:`` with ``admin.py``
    
  70. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  71. 
    
  72. Remove all your inner ``class Admin`` declarations from your models. They won't
    
  73. break anything if you leave them, but they also won't do anything. To register
    
  74. apps with the admin you'll move those declarations to an ``admin.py`` file;
    
  75. see `the admin`_ below for more details.
    
  76. 
    
  77. .. seealso::
    
  78. 
    
  79.     A contributor to djangosnippets__ has written a script that'll `scan your
    
  80.     models.py and generate a corresponding admin.py`__.
    
  81. 
    
  82.     __ https://djangosnippets.org/
    
  83.     __ https://djangosnippets.org/snippets/603/
    
  84. 
    
  85. Example
    
  86. ~~~~~~~
    
  87. 
    
  88. Below is an example ``models.py`` file with all the changes you'll need to make:
    
  89. 
    
  90. Old (0.96) ``models.py``::
    
  91. 
    
  92.     class Author(models.Model):
    
  93.         first_name = models.CharField(maxlength=30)
    
  94.         last_name = models.CharField(maxlength=30)
    
  95.         slug = models.CharField(maxlength=60, prepopulate_from=('first_name', 'last_name'))
    
  96. 
    
  97.         class Admin:
    
  98.             list_display = ['first_name', 'last_name']
    
  99. 
    
  100.         def __str__(self):
    
  101.             return '%s %s' % (self.first_name, self.last_name)
    
  102. 
    
  103. New (1.0) ``models.py``::
    
  104. 
    
  105.     class Author(models.Model):
    
  106.         first_name = models.CharField(max_length=30)
    
  107.         last_name = models.CharField(max_length=30)
    
  108.         slug = models.CharField(max_length=60)
    
  109. 
    
  110.         def __unicode__(self):
    
  111.             return u'%s %s' % (self.first_name, self.last_name)
    
  112. 
    
  113. New (1.0) ``admin.py``::
    
  114. 
    
  115.     from django.contrib import admin
    
  116.     from models import Author
    
  117. 
    
  118.     class AuthorAdmin(admin.ModelAdmin):
    
  119.         list_display = ['first_name', 'last_name']
    
  120.         prepopulated_fields = {
    
  121.             'slug': ('first_name', 'last_name')
    
  122.         }
    
  123. 
    
  124.     admin.site.register(Author, AuthorAdmin)
    
  125. 
    
  126. The Admin
    
  127. ---------
    
  128. 
    
  129. One of the biggest changes in 1.0 is the new admin. The Django administrative
    
  130. interface (``django.contrib.admin``) has been completely refactored; admin
    
  131. definitions are now completely decoupled from model definitions, the framework
    
  132. has been rewritten to use Django's new form-handling library and redesigned with
    
  133. extensibility and customization in mind.
    
  134. 
    
  135. Practically, this means you'll need to rewrite all of your ``class Admin``
    
  136. declarations. You've already seen in `models`_ above how to replace your ``class
    
  137. Admin`` with an ``admin.site.register()`` call in an ``admin.py`` file. Below are
    
  138. some more details on how to rewrite that ``Admin`` declaration into the new
    
  139. syntax.
    
  140. 
    
  141. Use new inline syntax
    
  142. ~~~~~~~~~~~~~~~~~~~~~
    
  143. 
    
  144. The new ``edit_inline`` options have all been moved to ``admin.py``. Here's an
    
  145. example:
    
  146. 
    
  147. Old (0.96)::
    
  148. 
    
  149.     class Parent(models.Model):
    
  150.         ...
    
  151. 
    
  152.     class Child(models.Model):
    
  153.         parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)
    
  154. 
    
  155. 
    
  156. New (1.0)::
    
  157. 
    
  158.     class ChildInline(admin.StackedInline):
    
  159.         model = Child
    
  160.         extra = 3
    
  161. 
    
  162.     class ParentAdmin(admin.ModelAdmin):
    
  163.         model = Parent
    
  164.         inlines = [ChildInline]
    
  165. 
    
  166.     admin.site.register(Parent, ParentAdmin)
    
  167. 
    
  168. See :ref:`admin-inlines` for more details.
    
  169. 
    
  170. Simplify ``fields``, or use ``fieldsets``
    
  171. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  172. 
    
  173. The old ``fields`` syntax was quite confusing, and has been simplified. The old
    
  174. syntax still works, but you'll need to use ``fieldsets`` instead.
    
  175. 
    
  176. Old (0.96)::
    
  177. 
    
  178.     class ModelOne(models.Model):
    
  179.         ...
    
  180. 
    
  181.         class Admin:
    
  182.             fields = (
    
  183.                 (None, {'fields': ('foo','bar')}),
    
  184.             )
    
  185. 
    
  186.     class ModelTwo(models.Model):
    
  187.         ...
    
  188. 
    
  189.         class Admin:
    
  190.             fields = (
    
  191.                 ('group1', {'fields': ('foo','bar'),   'classes': 'collapse'}),
    
  192.                 ('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}),
    
  193.             )
    
  194. 
    
  195. 
    
  196. New (1.0)::
    
  197. 
    
  198.     class ModelOneAdmin(admin.ModelAdmin):
    
  199.         fields = ('foo', 'bar')
    
  200. 
    
  201.     class ModelTwoAdmin(admin.ModelAdmin):
    
  202.         fieldsets = (
    
  203.             ('group1', {'fields': ('foo','bar'),   'classes': 'collapse'}),
    
  204.             ('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}),
    
  205.         )
    
  206. 
    
  207. 
    
  208. .. seealso::
    
  209. 
    
  210.     * More detailed information about the changes and the reasons behind them
    
  211.       can be found on the `NewformsAdminBranch wiki page`__
    
  212. 
    
  213.     * The new admin comes with a ton of new features; you can read about them in
    
  214.       the :doc:`admin documentation </ref/contrib/admin/index>`.
    
  215. 
    
  216.     __ https://code.djangoproject.com/wiki/NewformsAdminBranch
    
  217. 
    
  218. URLs
    
  219. ----
    
  220. 
    
  221. Update your root ``urls.py``
    
  222. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  223. 
    
  224. If you're using the admin site, you need to update your root ``urls.py``.
    
  225. 
    
  226. Old (0.96) ``urls.py``::
    
  227. 
    
  228.     from django.conf.urls.defaults import *
    
  229. 
    
  230.     urlpatterns = patterns('',
    
  231.         (r'^admin/', include('django.contrib.admin.urls')),
    
  232. 
    
  233.         # ... the rest of your URLs here ...
    
  234.     )
    
  235. 
    
  236. New (1.0) ``urls.py``::
    
  237. 
    
  238.     from django.conf.urls.defaults import *
    
  239. 
    
  240.     # The next two lines enable the admin and load each admin.py file:
    
  241.     from django.contrib import admin
    
  242.     admin.autodiscover()
    
  243. 
    
  244.     urlpatterns = patterns('',
    
  245.         (r'^admin/(.*)', admin.site.root),
    
  246. 
    
  247.         # ... the rest of your URLs here ...
    
  248.     )
    
  249. 
    
  250. Views
    
  251. -----
    
  252. 
    
  253. Use ``django.forms`` instead of ``newforms``
    
  254. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  255. 
    
  256. Replace ``django.newforms`` with ``django.forms`` -- Django 1.0 renamed the
    
  257. ``newforms`` module (introduced in 0.96) to plain old ``forms``. The
    
  258. ``oldforms`` module was also removed.
    
  259. 
    
  260. If you're already using the ``newforms`` library, and you used our recommended
    
  261. ``import`` statement syntax, all you have to do is change your import
    
  262. statements.
    
  263. 
    
  264. Old::
    
  265. 
    
  266.     from django import newforms as forms
    
  267. 
    
  268. New::
    
  269. 
    
  270.     from django import forms
    
  271. 
    
  272. If you're using the old forms system (formerly known as ``django.forms`` and
    
  273. ``django.oldforms``), you'll have to rewrite your forms. A good place to start
    
  274. is the :doc:`forms documentation </topics/forms/index>`
    
  275. 
    
  276. Handle uploaded files using the new API
    
  277. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  278. 
    
  279. Replace use of uploaded files -- that is, entries in ``request.FILES`` -- as
    
  280. simple dictionaries with the new
    
  281. :class:`~django.core.files.uploadedfile.UploadedFile`. The old dictionary
    
  282. syntax no longer works.
    
  283. 
    
  284. Thus, in a view like::
    
  285. 
    
  286.       def my_view(request):
    
  287.           f = request.FILES['file_field_name']
    
  288.           ...
    
  289. 
    
  290. ...you'd need to make the following changes:
    
  291. 
    
  292. ===================== =====================
    
  293. Old (0.96)            New (1.0)
    
  294. ===================== =====================
    
  295. ``f['content']``      ``f.read()``
    
  296. ``f['filename']``     ``f.name``
    
  297. ``f['content-type']`` ``f.content_type``
    
  298. ===================== =====================
    
  299. 
    
  300. Work with file fields using the new API
    
  301. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  302. 
    
  303. The internal implementation of :class:`django.db.models.FileField` have changed.
    
  304. A visible result of this is that the way you access special attributes (URL,
    
  305. filename, image size, etc.) of these model fields has changed. You will need to
    
  306. make the following changes, assuming your model's
    
  307. :class:`~django.db.models.FileField` is called ``myfile``:
    
  308. 
    
  309. =================================== ========================
    
  310. Old (0.96)                           New (1.0)
    
  311. =================================== ========================
    
  312. ``myfile.get_content_filename()``   ``myfile.content.path``
    
  313. ``myfile.get_content_url()``        ``myfile.content.url``
    
  314. ``myfile.get_content_size()``       ``myfile.content.size``
    
  315. ``myfile.save_content_file()``      ``myfile.content.save()``
    
  316. ``myfile.get_content_width()``      ``myfile.content.width``
    
  317. ``myfile.get_content_height()``     ``myfile.content.height``
    
  318. =================================== ========================
    
  319. 
    
  320. Note that the ``width`` and ``height`` attributes only make sense for
    
  321. :class:`~django.db.models.ImageField` fields. More details can be found in the
    
  322. :doc:`model API </ref/models/fields>` documentation.
    
  323. 
    
  324. Use ``Paginator`` instead of ``ObjectPaginator``
    
  325. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  326. 
    
  327. The ``ObjectPaginator`` in 0.96 has been removed and replaced with an improved
    
  328. version, :class:`django.core.paginator.Paginator`.
    
  329. 
    
  330. Templates
    
  331. ---------
    
  332. 
    
  333. Learn to love autoescaping
    
  334. ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  335. 
    
  336. By default, the template system now automatically HTML-escapes the output of
    
  337. every variable. To learn more, see :ref:`automatic-html-escaping`.
    
  338. 
    
  339. To disable auto-escaping for an individual variable, use the :tfilter:`safe`
    
  340. filter:
    
  341. 
    
  342. .. code-block:: html+django
    
  343. 
    
  344.       This will be escaped: {{ data }}
    
  345.       This will not be escaped: {{ data|safe }}
    
  346. 
    
  347. To disable auto-escaping for an entire template, wrap the template (or just a
    
  348. particular section of the template) in the :ttag:`autoescape` tag:
    
  349. 
    
  350. .. code-block:: html+django
    
  351. 
    
  352.       {% autoescape off %}
    
  353.          ... unescaped template content here ...
    
  354.       {% endautoescape %}
    
  355. 
    
  356. Less-common changes
    
  357. ===================
    
  358. 
    
  359. The following changes are smaller, more localized changes. They should only
    
  360. affect more advanced users, but it's probably worth reading through the list and
    
  361. checking your code for these things.
    
  362. 
    
  363. Signals
    
  364. -------
    
  365. 
    
  366. * Add ``**kwargs`` to any registered signal handlers.
    
  367. 
    
  368. * Connect, disconnect, and send signals via methods on the
    
  369.   :class:`~django.dispatch.Signal` object instead of through module methods in
    
  370.   ``django.dispatch.dispatcher``.
    
  371. 
    
  372. * Remove any use of the ``Anonymous`` and ``Any`` sender options; they no longer
    
  373.   exist. You can still receive signals sent by any sender by using
    
  374.   ``sender=None``
    
  375. 
    
  376. * Make any custom signals you've declared into instances of
    
  377.   :class:`django.dispatch.Signal` instead of anonymous objects.
    
  378. 
    
  379. Here's quick summary of the code changes you'll need to make:
    
  380. 
    
  381. =================================================  ======================================
    
  382. Old (0.96)                                         New (1.0)
    
  383. =================================================  ======================================
    
  384. ``def callback(sender)``                           ``def callback(sender, **kwargs)``
    
  385. ``sig = object()``                                 ``sig = django.dispatch.Signal()``
    
  386. ``dispatcher.connect(callback, sig)``              ``sig.connect(callback)``
    
  387. ``dispatcher.send(sig, sender)``                   ``sig.send(sender)``
    
  388. ``dispatcher.connect(callback, sig, sender=Any)``  ``sig.connect(callback, sender=None)``
    
  389. =================================================  ======================================
    
  390. 
    
  391. Comments
    
  392. --------
    
  393. 
    
  394. If you were using Django 0.96's ``django.contrib.comments`` app, you'll need to
    
  395. upgrade to the new comments app introduced in 1.0. See the upgrade guide
    
  396. for details.
    
  397. 
    
  398. Template tags
    
  399. -------------
    
  400. 
    
  401. :ttag:`spaceless` tag
    
  402. ~~~~~~~~~~~~~~~~~~~~~
    
  403. 
    
  404. The ``spaceless`` template tag now removes *all* spaces between HTML tags,
    
  405. instead of preserving a single space.
    
  406. 
    
  407. Local flavors
    
  408. -------------
    
  409. 
    
  410. U.S. local flavor
    
  411. ~~~~~~~~~~~~~~~~~
    
  412. 
    
  413. ``django.contrib.localflavor.usa`` has been renamed to
    
  414. ``django.contrib.localflavor.us``. This change was made to match the naming
    
  415. scheme of other local flavors. To migrate your code, all you need to do is
    
  416. change the imports.
    
  417. 
    
  418. Sessions
    
  419. --------
    
  420. 
    
  421. Getting a new session key
    
  422. ~~~~~~~~~~~~~~~~~~~~~~~~~
    
  423. 
    
  424. ``SessionBase.get_new_session_key()`` has been renamed to
    
  425. ``_get_new_session_key()``. ``get_new_session_object()`` no longer exists.
    
  426. 
    
  427. Fixtures
    
  428. --------
    
  429. 
    
  430. Loading a row no longer calls ``save()``
    
  431. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  432. 
    
  433. Previously, loading a row automatically ran the model's ``save()`` method. This
    
  434. is no longer the case, so any fields (for example: timestamps) that were
    
  435. auto-populated by a ``save()`` now need explicit values in any fixture.
    
  436. 
    
  437. Settings
    
  438. --------
    
  439. 
    
  440. Better exceptions
    
  441. ~~~~~~~~~~~~~~~~~
    
  442. 
    
  443. The old :exc:`EnvironmentError` has split into an
    
  444. :exc:`ImportError` when Django fails to find the settings module
    
  445. and a :exc:`RuntimeError` when you try to reconfigure settings
    
  446. after having already used them.
    
  447. 
    
  448. :setting:`LOGIN_URL` has moved
    
  449. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  450. 
    
  451. The :setting:`LOGIN_URL` constant moved from ``django.contrib.auth`` into the
    
  452. ``settings`` module. Instead of using ``from django.contrib.auth import
    
  453. LOGIN_URL`` refer to :setting:`settings.LOGIN_URL <LOGIN_URL>`.
    
  454. 
    
  455. :setting:`APPEND_SLASH` behavior has been updated
    
  456. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  457. 
    
  458. In 0.96, if a URL didn't end in a slash or have a period in the final
    
  459. component of its path, and :setting:`APPEND_SLASH` was True, Django would
    
  460. redirect to the same URL, but with a slash appended to the end. Now, Django
    
  461. checks to see whether the pattern without the trailing slash would be matched
    
  462. by something in your URL patterns. If so, no redirection takes place, because
    
  463. it is assumed you deliberately wanted to catch that pattern.
    
  464. 
    
  465. For most people, this won't require any changes. Some people, though, have URL
    
  466. patterns that look like this::
    
  467. 
    
  468.     r'/some_prefix/(.*)$'
    
  469. 
    
  470. Previously, those patterns would have been redirected to have a trailing
    
  471. slash. If you always want a slash on such URLs, rewrite the pattern as::
    
  472. 
    
  473.     r'/some_prefix/(.*/)$'
    
  474. 
    
  475. Smaller model changes
    
  476. ---------------------
    
  477. 
    
  478. Different exception from ``get()``
    
  479. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  480. 
    
  481. Managers now return a :exc:`~django.core.exceptions.MultipleObjectsReturned`
    
  482. exception instead of :exc:`AssertionError`:
    
  483. 
    
  484. Old (0.96)::
    
  485. 
    
  486.     try:
    
  487.         Model.objects.get(...)
    
  488.     except AssertionError:
    
  489.         handle_the_error()
    
  490. 
    
  491. New (1.0)::
    
  492. 
    
  493.   try:
    
  494.       Model.objects.get(...)
    
  495.   except Model.MultipleObjectsReturned:
    
  496.       handle_the_error()
    
  497. 
    
  498. ``LazyDate`` has been fired
    
  499. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  500. 
    
  501. The ``LazyDate`` helper class no longer exists.
    
  502. 
    
  503. Default field values and query arguments can both be callable objects, so
    
  504. instances of ``LazyDate`` can be replaced with a reference to ``datetime.datetime.now``:
    
  505. 
    
  506. Old (0.96)::
    
  507. 
    
  508.     class Article(models.Model):
    
  509.         title = models.CharField(maxlength=100)
    
  510.         published = models.DateField(default=LazyDate())
    
  511. 
    
  512. New (1.0)::
    
  513. 
    
  514.     import datetime
    
  515. 
    
  516.     class Article(models.Model):
    
  517.         title = models.CharField(max_length=100)
    
  518.         published = models.DateField(default=datetime.datetime.now)
    
  519. 
    
  520. ``DecimalField`` is new, and ``FloatField`` is now a proper float
    
  521. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  522. 
    
  523. Old (0.96)::
    
  524. 
    
  525.     class MyModel(models.Model):
    
  526.         field_name = models.FloatField(max_digits=10, decimal_places=3)
    
  527.         ...
    
  528. 
    
  529. New (1.0)::
    
  530. 
    
  531.     class MyModel(models.Model):
    
  532.         field_name = models.DecimalField(max_digits=10, decimal_places=3)
    
  533.         ...
    
  534. 
    
  535. If you forget to make this change, you will see errors about ``FloatField``
    
  536. not taking a ``max_digits`` attribute in ``__init__``, because the new
    
  537. ``FloatField`` takes no precision-related arguments.
    
  538. 
    
  539. If you're using MySQL or PostgreSQL, no further changes are needed. The
    
  540. database column types for ``DecimalField`` are the same as for the old
    
  541. ``FloatField``.
    
  542. 
    
  543. If you're using SQLite, you need to force the database to view the
    
  544. appropriate columns as decimal types, rather than floats. To do this, you'll
    
  545. need to reload your data. Do this after you have made the change to using
    
  546. ``DecimalField`` in your code and updated the Django code.
    
  547. 
    
  548. .. warning::
    
  549. 
    
  550.   **Back up your database first!**
    
  551. 
    
  552.   For SQLite, this means making a copy of the single file that stores the
    
  553.   database (the name of that file is the ``DATABASE_NAME`` in your
    
  554.   ``settings.py`` file).
    
  555. 
    
  556. To upgrade each application to use a ``DecimalField``, you can do the
    
  557. following, replacing ``<app>`` in the code below with each app's name:
    
  558. 
    
  559. .. code-block:: console
    
  560. 
    
  561.       $ ./manage.py dumpdata --format=xml <app> > data-dump.xml
    
  562.       $ ./manage.py reset <app>
    
  563.       $ ./manage.py loaddata data-dump.xml
    
  564. 
    
  565. Notes:
    
  566. 
    
  567. 1. It's important that you remember to use XML format in the first step of
    
  568.    this process. We are exploiting a feature of the XML data dumps that makes
    
  569.    porting floats to decimals with SQLite possible.
    
  570. 
    
  571. 2. In the second step you will be asked to confirm that you are prepared to
    
  572.    lose the data for the application(s) in question. Say yes; we'll restore
    
  573.    this data in the third step.
    
  574. 
    
  575. 3. ``DecimalField`` is not used in any of the apps shipped with Django prior
    
  576.    to this change being made, so you do not need to worry about performing
    
  577.    this procedure for any of the standard Django models.
    
  578. 
    
  579. If something goes wrong in the above process, just copy your backed up
    
  580. database file over the original file and start again.
    
  581. 
    
  582. Internationalization
    
  583. --------------------
    
  584. 
    
  585. :func:`django.views.i18n.set_language` now requires a POST request
    
  586. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  587. 
    
  588. Previously, a GET request was used. The old behavior meant that state (the
    
  589. locale used to display the site) could be changed by a GET request, which is
    
  590. against the HTTP specification's recommendations. Code calling this view must
    
  591. ensure that a POST request is now made, instead of a GET. This means you can
    
  592. no longer use a link to access the view, but must use a form submission of
    
  593. some kind (e.g. a button).
    
  594. 
    
  595. ``_()`` is no longer in builtins
    
  596. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  597. 
    
  598. ``_()`` (the callable object whose name is a single underscore) is no longer
    
  599. monkeypatched into builtins -- that is, it's no longer available magically in
    
  600. every module.
    
  601. 
    
  602. If you were previously relying on ``_()`` always being present, you should now
    
  603. explicitly import ``ugettext`` or ``ugettext_lazy``, if appropriate, and alias
    
  604. it to ``_`` yourself::
    
  605. 
    
  606.     from django.utils.translation import ugettext as _
    
  607. 
    
  608. HTTP request/response objects
    
  609. -----------------------------
    
  610. 
    
  611. Dictionary access to ``HttpRequest``
    
  612. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  613. 
    
  614. ``HttpRequest`` objects no longer directly support dictionary-style
    
  615. access; previously, both ``GET`` and ``POST`` data were directly
    
  616. available on the ``HttpRequest`` object (e.g., you could check for a
    
  617. piece of form data by using ``if 'some_form_key' in request`` or by
    
  618. reading ``request['some_form_key']``. This is no longer supported; if
    
  619. you need access to the combined ``GET`` and ``POST`` data, use
    
  620. ``request.REQUEST`` instead.
    
  621. 
    
  622. It is strongly suggested, however, that you always explicitly look in
    
  623. the appropriate dictionary for the type of request you expect to
    
  624. receive (``request.GET`` or ``request.POST``); relying on the combined
    
  625. ``request.REQUEST`` dictionary can mask the origin of incoming data.
    
  626. 
    
  627. Accessing ``HTTPResponse`` headers
    
  628. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  629. 
    
  630. ``django.http.HttpResponse.headers`` has been renamed to ``_headers`` and
    
  631. :class:`~django.http.HttpResponse` now supports containment checking directly.
    
  632. So use ``if header in response:`` instead of ``if header in response.headers:``.
    
  633. 
    
  634. Generic relations
    
  635. -----------------
    
  636. 
    
  637. Generic relations have been moved out of core
    
  638. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  639. 
    
  640. The generic relation classes -- ``GenericForeignKey`` and ``GenericRelation``
    
  641. -- have moved into the :mod:`django.contrib.contenttypes` module.
    
  642. 
    
  643. Testing
    
  644. -------
    
  645. 
    
  646. :meth:`django.test.Client.login` has changed
    
  647. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  648. 
    
  649. Old (0.96)::
    
  650. 
    
  651.     from django.test import Client
    
  652.     c = Client()
    
  653.     c.login('/path/to/login','myuser','mypassword')
    
  654. 
    
  655. New (1.0)::
    
  656. 
    
  657.     # ... same as above, but then:
    
  658.     c.login(username='myuser', password='mypassword')
    
  659. 
    
  660. Management commands
    
  661. -------------------
    
  662. 
    
  663. Running management commands from your code
    
  664. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  665. 
    
  666. :mod:`django.core.management` has been greatly refactored.
    
  667. 
    
  668. Calls to management services in your code now need to use
    
  669. ``call_command``. For example, if you have some test code that calls flush and
    
  670. load_data::
    
  671. 
    
  672.       from django.core import management
    
  673.       management.flush(verbosity=0, interactive=False)
    
  674.       management.load_data(['test_data'], verbosity=0)
    
  675. 
    
  676. ...you'll need to change this code to read::
    
  677. 
    
  678.       from django.core import management
    
  679.       management.call_command('flush', verbosity=0, interactive=False)
    
  680.       management.call_command('loaddata', 'test_data', verbosity=0)
    
  681. 
    
  682. Subcommands must now precede options
    
  683. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  684. 
    
  685. ``django-admin.py`` and ``manage.py`` now require subcommands to precede
    
  686. options. So:
    
  687. 
    
  688. .. code-block:: console
    
  689. 
    
  690.       $ django-admin.py --settings=foo.bar runserver
    
  691. 
    
  692. ...no longer works and should be changed to:
    
  693. 
    
  694. .. code-block:: console
    
  695. 
    
  696.       $ django-admin.py runserver --settings=foo.bar
    
  697. 
    
  698. Syndication
    
  699. -----------
    
  700. 
    
  701. ``Feed.__init__`` has changed
    
  702. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  703. 
    
  704. The ``__init__()`` method of the syndication framework's ``Feed`` class now
    
  705. takes an ``HttpRequest`` object as its second parameter, instead of the feed's
    
  706. URL. This allows the syndication framework to work without requiring the sites
    
  707. framework. This only affects code that subclasses ``Feed`` and overrides the
    
  708. ``__init__()`` method, and code that calls ``Feed.__init__()`` directly.
    
  709. 
    
  710. Data structures
    
  711. ---------------
    
  712. 
    
  713. ``SortedDictFromList`` is gone
    
  714. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  715. 
    
  716. ``django.newforms.forms.SortedDictFromList`` was removed.
    
  717. ``django.utils.datastructures.SortedDict`` can now be instantiated with
    
  718. a sequence of tuples.
    
  719. 
    
  720. To update your code:
    
  721. 
    
  722. 1. Use ``django.utils.datastructures.SortedDict`` wherever you were
    
  723.    using ``django.newforms.forms.SortedDictFromList``.
    
  724. 
    
  725. 2. Because ``django.utils.datastructures.SortedDict.copy`` doesn't
    
  726.    return a deepcopy as ``SortedDictFromList.copy()`` did, you will need
    
  727.    to update your code if you were relying on a deepcopy. Do this by using
    
  728.    ``copy.deepcopy`` directly.
    
  729. 
    
  730. Database backend functions
    
  731. --------------------------
    
  732. 
    
  733. Database backend functions have been renamed
    
  734. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  735. 
    
  736. Almost *all* of the database backend-level functions have been renamed and/or
    
  737. relocated. None of these were documented, but you'll need to change your code
    
  738. if you're using any of these functions, all of which are in :mod:`django.db`:
    
  739. 
    
  740. =======================================  ===================================================
    
  741. Old (0.96)                               New (1.0)
    
  742. =======================================  ===================================================
    
  743. ``backend.get_autoinc_sql``              ``connection.ops.autoinc_sql``
    
  744. ``backend.get_date_extract_sql``         ``connection.ops.date_extract_sql``
    
  745. ``backend.get_date_trunc_sql``           ``connection.ops.date_trunc_sql``
    
  746. ``backend.get_datetime_cast_sql``        ``connection.ops.datetime_cast_sql``
    
  747. ``backend.get_deferrable_sql``           ``connection.ops.deferrable_sql``
    
  748. ``backend.get_drop_foreignkey_sql``      ``connection.ops.drop_foreignkey_sql``
    
  749. ``backend.get_fulltext_search_sql``      ``connection.ops.fulltext_search_sql``
    
  750. ``backend.get_last_insert_id``           ``connection.ops.last_insert_id``
    
  751. ``backend.get_limit_offset_sql``         ``connection.ops.limit_offset_sql``
    
  752. ``backend.get_max_name_length``          ``connection.ops.max_name_length``
    
  753. ``backend.get_pk_default_value``         ``connection.ops.pk_default_value``
    
  754. ``backend.get_random_function_sql``      ``connection.ops.random_function_sql``
    
  755. ``backend.get_sql_flush``                ``connection.ops.sql_flush``
    
  756. ``backend.get_sql_sequence_reset``       ``connection.ops.sequence_reset_sql``
    
  757. ``backend.get_start_transaction_sql``    ``connection.ops.start_transaction_sql``
    
  758. ``backend.get_tablespace_sql``           ``connection.ops.tablespace_sql``
    
  759. ``backend.quote_name``                   ``connection.ops.quote_name``
    
  760. ``backend.get_query_set_class``          ``connection.ops.query_set_class``
    
  761. ``backend.get_field_cast_sql``           ``connection.ops.field_cast_sql``
    
  762. ``backend.get_drop_sequence``            ``connection.ops.drop_sequence_sql``
    
  763. ``backend.OPERATOR_MAPPING``             ``connection.operators``
    
  764. ``backend.allows_group_by_ordinal``      ``connection.features.allows_group_by_ordinal``
    
  765. ``backend.allows_unique_and_pk``         ``connection.features.allows_unique_and_pk``
    
  766. ``backend.autoindexes_primary_keys``     ``connection.features.autoindexes_primary_keys``
    
  767. ``backend.needs_datetime_string_cast``   ``connection.features.needs_datetime_string_cast``
    
  768. ``backend.needs_upper_for_iops``         ``connection.features.needs_upper_for_iops``
    
  769. ``backend.supports_constraints``         ``connection.features.supports_constraints``
    
  770. ``backend.supports_tablespaces``         ``connection.features.supports_tablespaces``
    
  771. ``backend.uses_case_insensitive_names``  ``connection.features.uses_case_insensitive_names``
    
  772. ``backend.uses_custom_queryset``         ``connection.features.uses_custom_queryset``
    
  773. =======================================  ===================================================