- 1. Release notes
- 1. Compatibility with Python
- 2. Support for third party libraries for older versions of Django
- 3. What's new in Django 2.0?
- 4. Minor functional
- 5. Changes without backwards compatibility in 2.0
- 1. Removed support for bytestrings in some places
- 2. Database backend API
- 3. Dropped support for Oracle 11.2
- 4. Default MySQL isolation level read committed
- 5. AbstractUser.last_name max_length increased to 150
- 6. QuerySet.reverse() and last() disabled after slicing
- 7. Form fields no longer accept optional arguments as positional arguments
- 8. call_command() checks the parameters it receives
- 9. Indexes no longer accept positional arguments
- 10. Foreign key constraints are now enabled in SQLite
- 6. Miscellaneous
- 7. Functionality deprecated in version 2.0
- 8. Miscellaneous
- 9. Functionality removed in version 2.0
The Django team announced the release of Django 2.0
This release starts with free-form semantic versioning in Django, but there are no significant backward compatibility changes (except that Python 2.7 has been removed), which was expected in the 2.0 release. The update should be the same as for previous releases.
Django 2.0 supports the following Python versions: 3.4, 3.5, and 3.6. These versions are highly recommended by the Django developers and only the latest versions of these Python version series are officially supported.
Django 1.11.x is the latest version to support Python 2.7
Django 2.0 will be the last version to support Python 3.4. If you plan on deploying Python 3.4 before the end of life for Django 2.0 (April 2019), then use Django 1.11 LTS (supported until April 2020). Please note, however, that the end of support for Python 3.4 is the end of March 2019.
Following the release of Django 2.0, the Developers are suggesting that third-party application developers drop support for all versions of Django prior to 1.11. At the same time, developers should be able to run their package tests with python -Wd in order to display error warnings. After fixing the error warning, the application should be compatible with Django 2.0.
The new django.urls.path() function allows us to simplify the url syntax and make it more readable. For example, this example from previous releases of Django:
Could be written like this
The new syntax supports URL parameter coercion type. In this example, the view will take the year keyword argument as an integer instead of a string. Also, URLs won't be as limited now because year is passed as an integer value, so for example year 10000 will now match, since year integers aren't limited to four digits as they would be in a regular expression.
The django.conf.urls.url() function from previous versions is now available as django.urls.re_path() . The old location remains for backwards compatibility. The old django.conf.urls.include() function is now imported from django.urls , so you can use it like from django.urls import include, path, re_path in your URLs addresses.
The administration panel now supports all major mobile devices. Older browsers may experience various levels of degradation.
The new Window expression allows you to add OVER to queries. You can use window functions and aggregate functions in an expression.
- New ModelAdmin.autocomplete_fields attribute and ModelAdmin.get_autocomplete_fields() method allow using Select2 search widget for ForeignKey and ManyToManyField .
- The default iteration count for the PBKDF2 password crypter has been increased from 36,000 to 100,000.
- Added MySQL support for AsGeoJSON function, GeoHash function, IsValid function, isvalid lookup and distance finder.
- Added Azimuth and LineLocatePoint functions supported by PostGIS and SpatiaLite .
- Any GEOSGeometry imported from GeoJSON now has its own set of SRID .
- Added OSMWidget.default_zoom attribute to set the default image zoom.
- Made metadata readable and editable on rasters through metadata, information and metadata attributes.
- It is allowed to pass driver-specific creation options for GDALRaster objects using papsz_options .
- Allowed to create GDALRaster objects in the internal virtual file system GDAL . Rasters can now be created and converted to in-memory binary data.
- New method GDALBand.color_interp() returns the color interpretation for the band.
- The new distinct argument for ArrayAgg determines whether the merged values will be distinct.
- New database function RandomUUID returns version 4 UUID. This requires the use of the pgcrypto PostgreSQL extension, which can be enabled with the new migration operation CryptoExtension .
- django.contrib.postgres.indexes.GinIndex now supports fastupdate and gin_pending_list_limit options.
- The new GistIndex class allows you to create GiST indexes on the database. The new BtreeGistExtension migration installs the btree_gist extension to add support for operator classes that are not built-in.
- inspectdb can now use JSONField and various RangeFields ( django.contrib.postgres should be in INSTALLED_APPS ).
- Added protocol keyword argument to GenericSitemap constructor.
- cache.set_many() now returns a list of keys that were not inserted. For embedded backends, failed inserts can only happen on memcached .
- File.open() can be used as a context manager, for example. with file.open() as f: .
- New date_attrs and time_attrs arguments for SplitDateTimeWidget and SplitHiddenDateTimeWidget allow you to specify different HTML attributes for DateInput and TimeInput subwidgets (or hidden).
- New method Form.errors.get_json_data() returns form errors as a dictionary suitable for inclusion in a JSON response.
- New attribute ContextMixin.extra_context allows you to add context to View.as_view() .
- inspectdb now translates unsigned MySQL integer columns to PositiveIntegerField or PositiveSmallIntegerField .
- New option makemessages --add-location defines the comment format in PO files.
- loaddata can now read from stdin .
- New option diffsettings - output allows you to format the output in the unified format diff .
- In Oracle, inspection can now consider AutoField if the column is created as an identity column.
- MySQL dbshell now supports TLS client certificates.
- New option squashmigrations --squashed-name allows you to name a squashed migration.
- New database function StrIndex finds the starting index of a string within another string.
- In Oracle, AutoField and BigAutoField are now created as identity columns.
- New parameter chunk_size QuerySet.iterator() controls the number of rows selected by the Python database client when streaming results from the database. For databases that don't support server-side cursors, it controls the number of results Django gets from the database adapter.
- QuerySet.earliest() , QuerySet.latest() and Meta.get_latest_by now allow multiple fields to be ordered.
- Added ExtractQuarter function to extract quarter from DateField and DateTimeField .
- Added TruncQuarter function to truncate DateField and DateTimeField on the first day of the quarter.
- Added parameter db_tablespace for class indexes.
- If the database supports its own duration field ( Oracle and PostgreSQL ), Extract now works with DurationField .
- Added QuerySet.select_for_update() argument, supported by PostgreSQL and Oracle , to lock only rows from specific tables, not all selected tables. This can be useful, especially if select_for_update() is used in conjunction with select_related() .
- New parameter field_name QuerySet.in_bulk() allows you to get results based on any unique field in the model.
- CursorWrapper.callproc() now uses an optional keyword parameter dictionary if the backend supports this feature. Django's built-in servers only support Oracle.
- New method connection.execute_wrapper() allows you to set wrappers around executing database queries.
- New filter argument for built-in aggregates allows you to add different conventions to multiple aggregates on the same fields or relationships.
- Added support for expressions in Meta.ordering .
- New named parameter QuerySet.values_list() allows you to get results as named tuples.
- New class FilteredRelation allows you to add ON to requests.
- Added Paginator.get_page() to provide a documented template for handling invalid page numbers.
- The runserver method for the Web server supports HTTP 1.1.
- To increase the usefulness of Engine.get_default() in third party applications, it now returns the first engine if multiple DjangoTemplates engines are configured in TEMPLATES instead of throwing NotperlyConfigured .
- Custom template tags can now only accept keyword arguments.
- Added support for streaming LiveServerTestCase .
- Added settings that allow setting test tablespace parameters for Oracle: DATAFILE_SIZE , DATAFILE_TMP_SIZE , DATAFILE_EXTSIZE and DATAFILE_TMP_EXTSIZE .
- New ProhibitNullCharactersValidator prohibits the null character in the input of the CharField form field and its subclasses. Zero character input has been observed from vulnerability scanning tools. Most databases silently discard null characters, but psycopg2 2.7+ throws an exception when trying to store a null character in a char / text field with PostgreSQL .
In order to support native Python 2 strings, older versions of Django had to accept both bytes and unicode strings. Now that Python 2 support is being dropped, bytes should only occur around I/O boundaries (e.g. handling binary fields or HTTP streams). You may need to update your code to limit the use of bytes to the bare minimum since Django no longer accepts bytes in certain codes.
For example, reverse() now uses str() instead of force_text() to force the arguments and kwargs it receives before placing them in the URL. For bytes, this creates a string with the unwanted b prefix, plus extra quotes (str (b'foo ') - "b'foo") . To adapt, call decode() on a byte sequence before passing it to reverse() .
This section describes changes that may be required in third-party database backends.
- Methods DatabaseOperations.datetime_cast_date_sql() , datetime_cast_time_sql() , datetime_trunc_sql() , datetime_extract_sql() and date_interval_sql() now only return the SQL to perform the operation instead of SQL and parameter list.
- Third party database databases should add the DatabaseWrapper.display_name attribute with the name of the database your backend is working with. Django can use it in various messages such as system checks.
- The first argument to SchemaEditor._alter_column_type_sql() is now a model, not a table.
- The first argument to SchemaEditor._create_index_name() is now table_name , not a model.
- To enable FOR UPDATE support, set DatabaseFeatures.has_select_for_update_of = True . If the database requires the OF arguments to be columns and not tables, set DatabaseFeatures.select_for_update_of_column = True .
- To enable support for Window expressions, set the DatabaseFeatures.supports_over_clause parameter to True . You may need to tweak the DatabaseOperations.window_start_rows_start_end() and/or window_start_range_start_end() methods.
- Third party database databases must add the DatabaseOperations.cast_char_field_without_max_length attribute with the database data type to be used in the Cast function for CharField if the max_length argument is not specified.
- The first argument to DatabaseCreation._clone_test_db() and get_test_db_clone_settings() is now a suffix instead of a number (in case you want to rename signatures in your server for consistency). Now django.test passes these values as strings instead of integers.
- Third party database databases should add a stub-based DatabaseIntrospection.get_sequences() method to BaseDatabaseIntrospection .
The end of uplink support for Oracle 11.2 is December 2020. Django 1.11 will be supported until April 2020, which is close to that date. Django 2.0 officially supports Oracle 12.1+.
MySQL's default isolation level, repeatable reads, can result in data loss in typical Django usage. To prevent this and for consistency with other databases, the default isolation level is now read committed. You can use the DATABASES option to use a different isolation level if needed.
Enabled migration for django.contrib.auth.models.User.last_name. If you have a user model that inherits from AbstractUser, then you need to create and apply a database migration for your user model.
If you want to keep the 30 character limit for last names, use a custom form:
from django.contrib.auth.forms import UserChangeForm class MyUserChangeForm(UserChangeForm): last_name = forms.CharField(max_length=30, required=False)
If you want to keep this restriction in the admin when editing users, set UserAdmin.form to use this form:
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User class MyUserAdmin(UserAdmin): form = MyUserChangeForm admin.site.unregister(User) admin.site.register(User, MyUserAdmin)
Calling QuerySet.reverse() or last() on a fragmented queryset produces unexpected results due to the fact that the slice is applied after the reordering. This is prohibited, for example:
>>> Model.objects.all()[:2].reverse() Traceback (most recent call last): ... TypeError: Cannot reverse a query once a slice has been taken.
To prevent run-time errors due to incorrect ordering of form field arguments, optional built-in form field arguments are no longer accepted as positional arguments. For example:
throws an exception and is replaced by:
Now call_command() checks that the called command's argument parser defines all parameters passed to call_command().
For custom control commands that use options not created with parser.add_argument() , add the stealth_options attribute to the command:
class MyCommand(BaseCommand): stealth_options = ('option_name', ...)
models.Index(['headline', '-pub_date'], 'index_name')
throws an exception and is replaced by:
models.Index(fields=['headline', '-pub_date'], name='index_name')
This will show up as a backward-incompatible change (IntegrityError: FOREIGN KEY integrity constraint) when attempting to save an existing model instance that violates the foreign key constraint.
Foreign keys are now created with DEFERRABLE INITIALLY DEFERRED instead of DEFERRABLE IMMEDIATE. Thus tables may need to be rebuilt to recreate foreign keys with the new definition, especially if you use this pattern:
from django.db import transaction with transaction.atomic(): Book.objects.create(author_id=1) Author.objects.create(id=1)
If you don't recreate the foreign key as DEFERRED, the first create() will fail if foreign key constraints are applied.
Back up your database first! After upgrading to Django 2.0, you can rebuild tables using a script like this:
from django.apps import apps from django.db import connection for app in apps.get_app_configs(): for model in app.get_models(include_auto_created=True): if model._meta.managed and not (model._meta.proxy or model._meta.swapped): for base in model.__bases__: if hasattr(base, '_meta'): base._meta.local_many_to_many =  model._meta.local_many_to_many =  with connection.schema_editor() as editor: editor._remake_table(model)
This script has not been widely tested and needs to be adapted for different cases such as multiple databases. Feel free to make improvements.
Also, due to the SQLite table modification restriction, it is not allowed to perform RenameModel and RenameField operations on models or fields referenced by other models in a transaction. To allow migrations containing these operations, you must set the Migration.atomic attribute to False.
- The SessionAuthenticationMiddleware class has been removed. It provided no functionality as session authentication is unconditionally included in Django 1.10.
- Default HTTP error handlers (handler404 etc.) are now callers instead of dotted Python path strings. Django supports callable references because they provide better performance and debugging capabilities.
- RedirectView no longer disables NoReverseMatch if pattern_name does not exist.
- When USE_L10N is off, FloatField and DecimalField now respect DECIMAL_SEPARATOR and THOUSAND_SEPARATOR during validation. For example, with the settings, the input "1.345" is now converted to 1345 instead of 1.345.:
USE_L10N = False USE_THOUSAND_SEPARATOR = True DECIMAL_SEPARATOR = ',' THOUSAND_SEPARATOR = '.'
- Subclasses of AbstractBaseUser are no longer required to implement get_short_name() and get_full_name() . (Base implementations that raise NotImplementedError are removed.) Django.contrib.admin uses these methods if they are implemented, but does not require them. Third party applications using these methods may want to take a similar approach.
- assertNumQueries() now ignores connection configuration requests. Previously, if a new database connection was opened in a test, these queries could be included as part of countNumQueries() .
- The Oracle test tablespace default size is increased from 20M to 50M, and the default autoextend size is increased from 10M to 25M.
- To improve performance when streaming large result sets from the database, QuerySet.iterator() now fetches 2000 rows at a time instead of 100. The old behavior can be restored using the chunk_size parameter. For example:
- The primary key of a model instance now appears in the model's . str () method by default, e.g. Question object (1).
- makemigrations now detects changes to the limit_choices_to field of the model parameter. Add this to your existing migrations, or accept an auto-generated migration for fields that use it.
- Executing queries that require automatic spatial transformations now raises NotImplementedError for MySQL instead of silence using untransformed geometries.
- django.core.exceptions.DjangoRuntimeWarning is removed. It was only used in cache as an intermediate class in the CacheKeyWarning inheritance of RuntimeWarning .
- Renamed BaseExpression._output_field to output_field . You may need to update user expressions.
- In older versions, shapes and forms combine their media with Media Widgets by merging them. The union now attempts to preserve the relative order of the elements in each list. MediaOrderConflictWarning is issued if the order cannot be saved.
- django.contrib.gis.gdal.OGRException is removed. This has been an alias for GDALException since Django 1.8.
- Support for GEOS 3.3.x is disabled.
- The way data is selected for GeometryField has been changed to improve performance, and in raw SQL queries these fields should now be wrapped in connection.ops.select .
The Field.from_db_value() and Expression.convert_value() context argument is not used because it is always an empty dictionary. The signature of both methods is now:
(self, value, expression, connection)
(self, value, expression, connection, context)
Support for the old signature in custom fields and expressions continues until Django 3.0.
- The django.db.backends.postgresql_psycopg2 module has been deprecated in favor of django.db.backends.postgresql . It was an alias in Django 1.9. This only affects code that is directly imported from a module. The DATABASES option can still use 'django.db.backends.postgresql_psycopg2' , though you can simplify this by using the name 'django.db.backends.postgresql' added to Django 1.9.
- django.shortcuts.render_to_response() has been deprecated in favor of django.shortcuts.render() . render() takes the same arguments, except that it also requires a request.
- The value DEFAULT_CONTENT_TYPE is deprecated. It doesn't play well with third party applications and is deprecated as HTML5 has mostly replaced XHTML .
- HttpRequest.xreadlines() has been deprecated in favor of on-demand iteration.
- The field_name keyword argument for QuerySet.earliest() and QuerySet.latest() has been deprecated in favor of passing field names as arguments. Write .earliest('pub_date') instead of .earliest(field_name = 'pub_date') .
Django 2.0 also removed all features that were marked as deprecated in versions 1.9 and 1.10.
For Django I recommend Timeweb hoster VDS server .