- 1. Примітки до випуску
- 1. Сумісність з Python
- 2. Підтримка третьосторонніх бібліотек для старих версій Django
- 3. Що нового в Django 2.0?
- 4. Мінорний функціонал
- 5. Зміни без зворотної сумісності до 2.0
- 1. В деяких місцях видалена підтримка bytestrings
- 2. Backend API бази даних
- 3. Відкинута підтримка Oracle 11.2
- 4. Рівень ізоляції MySQL за замовчуванням read committed
- 5. Максимальну довжину AbstractUser.last_name збільшено до 150
- 6. QuerySet.reverse() і last() заборонені після slicing
- 7. Поля форми більше не приймають необов'язкові аргументи як позиційні аргументи
- 8. call_command() перевіряє параметри, які вона отримує
- 9. Індекси більше не приймають позиційні аргументи
- 10. Обмеження зовнішнього ключа тепер включені в SQLite
- 6. Різне
- 7. Функціонал, застарілий у версії 2.0
- 8. Різне
- 9. Функціонал, видалений у версії 2.0
Django анонсувала випуск Django 2.0
Цей випуск починається з використання в Django вільної форми семантичного управління версіями, але немає істотних змін у зворотній сумісності (за винятком того, що було видалено Python 2.7), що було очікуваним у випуску 2.0. Оновлення має бути таким самим, як і для попередніх випусків.
Примітки до випуску
Сумісність з Python
Django 2.0 підтримує такі версії Python: 3.4, 3.5 та 3.6. Розробники Django рекомендують саме ці версії і офіційно підтримують лише останні версії даних версійних серій Python.
Django 1.11.x є останньою версією, яка підтримує Python 2.7
Django 2.0 стане останньою версією із підтримкою Python 3.4. Якщо ви плануєте розгортання Python 3.4 до кінця терміну служби для Django 2.0 (квітень 2019 року), використовуйте Django 1.11 LTS (підтримуваний до квітня 2020 року). Зверніть увагу, однак, що кінець підтримки Python 3.4 – кінець березня 2019 року.
Підтримка третьосторонніх бібліотек для старих версій Django
Після випуску Django 2.0 Розробники пропонують стороннім розробникам додатків відмовитись від підтримки всіх версій Django до 1.11. У той же час розробники повинні мати можливість запускати тести свого пакета за допомогою python-Wd , щоб відображати попередження про помилки. Після внесення виправлень для попередження про помилку, програма повинна бути сумісна з Django 2.0.
Що нового в Django 2.0?
Спрощений синтаксис маршрутизації URL-адрес
Нова функція django.urls.path() дозволяє спростити синтаксис url-адрес і зробити його більш читаним. Наприклад, цей приклад із попередніх випусків Django:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
Може бути написаний таким чином
path('articles/<int:year>/', views.year_archive),
Новий синтаксис підтримує тип примусу параметрів URL-адреси. У цьому прикладі представлення прийматиме аргумент ключового слова year як ціле число, а не як рядок. Крім того, URL-адреси не будуть тепер так обмежені, оскільки year передається як цілісне значення, то, наприклад, рік 10000 тепер буде відповідати, оскільки цілі числа року не обмежені чотирма цифрами, тому що якби вони знаходилися в регулярному вираженні.
Функція django.conf.urls.url() із попередніх версій тепер доступна як django.urls.re_path() . Старе розташування залишається для зворотної сумісності. Стара функція django.conf.urls.include() тепер імпортується з django.urls , тому ви можете використовувати її як from django.urls import include, path, re_path у ваших URL- адреси.
Contrib.admin для мобільних пристроїв
Тепер панель адміністрування підтримує всі основні мобільні пристрої. Старі браузери можуть випробовувати різні рівні деградації.
Віконні вирази
Новий вираз Window дозволяє додати OVER до запитів. Ви можете використовувати функції вікна та агрегатні функції у виразі.
Мінорний функціонал
django.contrib.admin
- Нові ModelAdmin.autocomplete_fields аттрибут та метод ModelAdmin.get_autocomplete_fields() дозволяють використовувати Select2 пошуковий віджет для ForeignKey та ManyToManyField .
django.contrib.auth
- Лічильник ітерацій за замовчуванням для шифрувальника пароля PBKDF2 збільшено з 36 000 до 100 000.
django.contrib.gis
- Додана підтримка MySQL для функції AsGeoJSON , функції GeoHash , функції IsValid , пошуку isvalid та пошуку відстаней.
- Додані функції Azimuth та LineLocatePoint , що підтримуються PostGIS та SpatiaLite .
- Будь-яка GEOSGeometry , імпортована з GeoJSON , тепер має свій набір SRID .
- Доданий атрибут OSMWidget.default_zoom , щоб настроїти масштаб за промовчанням.
- Зроблено метадані, читані та редаговані на растрах через атрибути метаданих, інформації та метаданих.
- Дозволено передавати параметри створення конкретного драйвера для об'єктів GDALRaster за допомогою papsz_options .
- Дозволено створювати об'єкти GDALRaster у внутрішній віртуальній файловій системі GDAL . Тепер Rasters можна створювати та перетворювати на двійкові дані в пам'яті.
- Новий метод GDALBand.color_interp() повертає інтерпретацію кольору для смуги.
django.contrib.postgres
- Новий distinct аргумент для ArrayAgg визначає, чи будуть об'єднані значення різними.
- Нова функція бази даних RandomUUID повертає UUID версії 4. Для цього потрібне використання розширення pgcrypto PostgreSQL , яке можна активувати за допомогою нової операції міграції CryptoExtension .
- django.contrib.postgres.indexes.GinIndex тепер підтримує параметри fastupdate та gin_pending_list_limit .
- Новий клас GistIndex дозволяє створювати індекси GiST у базі даних. У новій операції міграції BtreeGistExtension встановлюється розширення btree_gist, щоб додати підтримку класів операторів, які не вбудовані.
- inspectdb тепер може використовувати JSONField і різні RangeFields ( django.contrib.postgres має бути у INSTALLED_APPS ).
django.contrib.sitemaps
- Доданий аргумент ключового слова protocol у конструктор GenericSitemap .
Кеш
- cache.set_many() тепер повертає список ключів, які не були вставлені. Для вбудованих бекендів невдалі вставки можуть відбутися лише на memcached .
Зберігання файлів
- File.open() може використовуватися як менеджер контексту, наприклад. з file.open() як f: .
Форми
- Нові аргументи date_attrs та time_attrs для SplitDateTimeWidget та SplitHiddenDateTimeWidget дозволяють вказувати різні атрибути HTML для підвіджетів DateInput та TimeInput (або прихованих).
- Новий метод Form.errors.get_json_data() повертає помилки форми як словник, придатний для включення у відповідь JSON.
Загальні перегляди
- Новий атрибут ContextMixin.extra_context дозволяє додати контекст до View.as_view() .
Команди керування
- inspectdb тепер перекладає беззнакові цілі стовпці MySQL у PositiveIntegerField або PositiveSmallIntegerField .
- Нова опція makemessages --add-location визначає формат коментаря у файлах PO.
- loaddata тепер може читати з stdin .
- Нова опція diffsettings - output дозволяє форматувати виведення в уніфікованому форматі diff .
- В Oracle інспекція тепер може розглядати AutoField , якщо стовпець створено як стовпець ідентифікатора.
- У MySQL dbshell тепер підтримує клієнтські TLS-сертифікати.
Міграції
- Нова опція squashmigrations --squashed-name дозволяє називати стислу міграцію.
Моделі
- Нова функція бази даних StrIndex знаходить початковий індекс рядка всередині іншого рядка.
- У Oracle, AutoField та BigAutoField тепер створюються як стовпці ідентифікації.
- Новий параметр chunk_size QuerySet.iterator() керує кількістю рядків, вибраних клієнтом бази даних Python при потоковій передачі результатів з бази даних. Для баз даних, які не підтримують серверні курсори, він контролює кількість результатів, отриманих Django із адаптера бази даних.
- QuerySet.earliest() , QuerySet.latest() та Meta.get_latest_by тепер дозволяють упорядковувати кілька полів.
- Додана функція ExtractQuarter для вилучення кварталу з DateField та DateTimeField .
- Додана функція TruncQuarter для обрізання DateField та DateTimeField у перший день кварталу.
- Доданий параметр db_tablespace для індексів класу.
- Якщо база даних підтримує власне поле тривалості ( Oracle і PostgreSQL ), Extract тепер працює з DurationField .
- Доданий аргумент QuerySet.select_for_update(), підтримуваний PostgreSQL і Oracle , для блокування лише рядків з певних таблиць, а не всіх вибраних таблиць. Це може бути корисно, якщо select_for_update() використовується в поєднанні з select_related() .
- Новий параметр field_name QuerySet.in_bulk() дозволяє отримувати результати на основі будь-якого унікального поля моделі.
- CursorWrapper.callproc() тепер використовує необов'язковий словник параметрів ключового слова, якщо бекенд підтримує цю функцію. Вбудовані сервери Django підтримують лише Oracle.
- Новий метод connection.execute_wrapper() дозволяє встановлювати обгортки навколо виконання запитів до бази даних.
- Новий аргумент фільтра для вбудованих агрегатів дозволяє додавати різні умовні позначення в кілька агрегатів за тими ж полями або відносинами.
- Додана підтримка виразів у Meta.ordering .
- Новий іменований параметр QuerySet.values_list() дозволяє отримувати результати як іменовані кортежі.
- Новий клас FilteredRelation дозволяє додати ON до запитів.
Розбиття на сторінки
- Доданий Paginator.get_page() , щоб забезпечити документований шаблон обробки неприпустимих номерів сторінок.
Запити та відповіді
- Метод runserver для Веб-сервера підтримує HTTP 1.1.
Шаблони
- Щоб підвищити корисність Engine.get_default() у сторонніх додатках, тепер він повертає перший движок, якщо кілька механізмів DjangoTemplates налаштовані на TEMPLATES замість викидати NotperlyConfigured .
- Теги шаблонів користувача тепер можуть приймати аргументи тільки для ключового слова.
Тести
- Додана підтримка потокової передачі LiveServerTestCase .
- Додані настройки, які дозволяють налаштовувати параметри тестового табличного простору для Oracle: DATAFILE_SIZE , DATAFILE_TMP_SIZE , DATAFILE_EXTSIZE та DATAFILE_TMP_EXTSIZE .
Валідатори
- Новий ProhibitNullCharactersValidator забороняє нульовий символ у введенні поля форми CharField та його підкласів. Нульове введення символів спостерігалося з інструментів сканування вразливостей. Більшість баз даних мовчки відкидають нульові символи, але psycopg2 2.7+ створює виняток, намагаючись зберегти нульовий символ у полі char / text з PostgreSQL .
Зміни без зворотної сумісності до 2.0
В деяких місцях видалена підтримка bytestrings
Щоб підтримувати власні рядки Python 2, більш старі версії Django мали приймати як байти, так і рядки unicode. Тепер, коли підтримка Python 2 відкидається, байти мають зустрічатися лише навколо меж введення/виведення (наприклад, обробка двійкових полів або потоків HTTP). Можливо, вам доведеться оновити свій код, щоб обмежити використання байтів до мінімуму, оскільки Django більше не приймає байти у певних кодах.
Наприклад, reverse() тепер використовує str() замість force_text() для примусу аргументів і kwargs , які він отримує, до їхнього розміщення в URL-адресі. Для байтів це створює рядок з небажаним префіксом b, а також додаткові лапки (str(b'foo') - «b'foo») . Щоб адаптуватися, викличте decode() у байтовій послідовності, перш ніж передавати його в reverse() .
Backend API бази даних
У цьому розділі описуються зміни, які можуть знадобитися в сторонніх базах даних.
- методи замість SQL та список параметрів.
- Сторонні бази даних бази даних повинні додати атрибут DatabaseWrapper.display_name з ім'ям бази даних, з якою працює ваш бекенд. Django може використовувати його у різних повідомленнях, наприклад, у системних перевірках.
- Перший аргумент SchemaEditor._alter_column_type_sql() тепер є моделлю, а не таблицею.
- Перший аргумент SchemaEditor._create_index_name() тепер є table_name , а не моделлю.
- Щоб увімкнути FOR UPDATE підтримку, встановіть DatabaseFeatures.has_select_for_update_of=True . Якщо база даних вимагає, щоб аргументи OF були стовпцями, а не таблицями, встановіть DatabaseFeatures.select_for_update_of_column=True .
- Щоб увімкнути підтримку виразів Window , встановіть для параметра DatabaseFeatures.supports_over_clause значення True . Можливо, вам доведеться налаштувати методи DatabaseOperations.window_start_rows_start_end() та/або window_start_range_start_end() .
- Сторонні бази даних бази даних повинні додати атрибут DatabaseOperations.cast_char_field_without_max_length з типом даних бази даних, який буде використовуватися у функції Cast для CharField , якщо аргумент max_length не вказано.
- Перший аргумент DatabaseCreation._clone_test_db() та get_test_db_clone_settings() тепер є суфіксом, а не числом (у разі, якщо ви хочете перейменувати підписи у своєму сервері для узгодженості). Тепер django.test передає ці значення як рядки, а чи не як цілі числа.
- Сторонні бази даних бази даних повинні додати метод DatabaseIntrospection.get_sequences() на основі заглушки у BaseDatabaseIntrospection .
Відкинута підтримка Oracle 11.2
Закінчення підтримки по висхідній лінії для Oracle 11.2 – грудень 2020 року. Django 1.11 підтримуватиметься до квітня 2020 року, який майже досягне цієї дати. Django 2.0 офіційно підтримує Oracle 12.1+.
Рівень ізоляції MySQL за замовчуванням read committed
Рівень ізоляції MySQL за промовчанням, що повторюється читання, може призвести до втрати даних при типовому використанні Django. Щоб запобігти цьому і для узгодженості з іншими базами даних, рівень ізоляції за замовчуванням тепер read committed. Ви можете використовувати параметр DATABASES для використання іншого рівня ізоляції, якщо це необхідно.
Максимальну довжину AbstractUser.last_name збільшено до 150
Увімкнено міграцію для django.contrib.auth.models.User.last_name. Якщо у вас є власна модель, успадкована від AbstractUser, вам необхідно створити і застосувати міграцію бази даних для вашої моделі користувача.
Якщо ви хочете зберегти обмеження на 30 символів для прізвищ, використовуйте форму користувача:
from django.contrib.auth.forms import UserChangeForm class MyUserChangeForm(UserChangeForm): last_name = forms.CharField(max_length=30, required=False)
Якщо ви бажаєте зберегти це обмеження в адміні під час редагування користувачів, установіть UserAdmin.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)
QuerySet.reverse() і last() заборонені після slicing
Виклик QuerySet.reverse() або last() на фрагментованому наборі запитів призводить до несподіваних результатів через те, що зріз застосовується після переупорядкування. Це заборонено, наприклад:
>>> Model.objects.all()[:2].reverse() Traceback (most recent call last): ... TypeError: Cannot reverse a query once a slice has been taken.
Поля форми більше не приймають необов'язкові аргументи як позиційні аргументи
Щоб запобігти помилкам часу виконання через неправильне впорядкування аргументів поля форми, необов'язкові аргументи вбудованих полів форми більше не приймаються як позиційні аргументи. Наприклад:
forms.IntegerField(25, 10)
викликає виняток і замінюється на:
forms.IntegerField(max_value=25, min_value=10)
call_command() перевіряє параметри, які вона отримує
Тепер call_command() перевіряє, що парсер аргументів команди, що викликається, визначає всі параметри, передані в call_command().
Для команд команд керування, які використовують параметри, не створені за допомогою parser.add_argument() , додайте в команду атрибут stealth_options :
class MyCommand(BaseCommand): stealth_options = ('option_name', ...)
Індекси більше не приймають позиційні аргументи
Наприклад:
models.Index(['headline', '-pub_date'], 'index_name')
викликає виняток і замінюється на:
models.Index(fields=['headline', '-pub_date'], name='index_name')
Обмеження зовнішнього ключа тепер включені в SQLite
Це буде відображатися як зворотно-несумісна зміна (обмеження цілісності IntegrityError: FOREIGN KEY) при спробі зберегти існуючий екземпляр моделі, що порушує обмеження зовнішнього ключа.
Зовнішні ключі тепер створюються з DEFERRABLE INITIALLY DEFERRED замість DEFERRABLE IMMEDIATE. Таким чином, таблиці, можливо, потрібно перебудувати для відтворення зовнішніх ключів з новим визначенням, особливо якщо ви використовуєте такий шаблон:
from django.db import transaction with transaction.atomic(): Book.objects.create(author_id=1) Author.objects.create(id=1)
Якщо ви не відтворюєте зовнішній ключ як DEFERRED, перший create() завершиться помилкою, якщо будуть застосовані обмеження зовнішнього ключа.
Спершу створіть резервну копію бази даних! Після оновлення до Django 2.0 ви можете перебудувати таблиці, використовуючи скрипт, подібний до цього:
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)
Цей скрипт не отримав широкого тестування і потребує адаптації для різних випадків, таких як кілька баз даних. Не соромтеся вносити вдосконалення.
Крім того, через обмеження на зміну таблиці SQLite забороняється виконувати операції RenameModel та RenameField для моделей або полів, на які посилаються інші моделі у транзакції. Щоб дозволити міграції, що містять ці операції, необхідно встановити для атрибута Migration.atomic значення False.
Різне
- Клас SessionAuthenticationMiddleware видалено. Він не забезпечував функціональності, оскільки автентифікація сеансу беззастережно включена до Django 1.10.
- Обробники помилок HTTP за промовчанням (handler404 і т. д.) Тепер є викликаючими, а не пунктирними рядками шляху Python. Django підтримує посилання, оскільки вони забезпечують кращу продуктивність і можливість налагодження.
- RedirectView більше не відключає NoReverseMatch , якщо pattern_name не існує.
- Коли USE_L10N вимкнено, FloatField та DecimalField тепер дотримуються DECIMAL_SEPARATOR та THOUSAND_SEPARATOR під час перевірки. Наприклад, з налаштуваннями, введення «1.345» тепер перетворено на 1345 замість 1.345.:
USE_L10N = False USE_THOUSAND_SEPARATOR = True DECIMAL_SEPARATOR = ',' THOUSAND_SEPARATOR = '.'
- Підкласи AbstractBaseUser більше не потрібні для реалізації get_short_name() та get_full_name() . (Базові реалізації, які піднімають NotImplementedError , видаляються.) Django.contrib.admin використовує ці методи, якщо вони реалізовані, але не вимагають їх. Сторонні програми, які використовують ці методи, можуть захотіти застосувати аналогічний підхід.
- Параметри формату FIRST_DAY_OF_WEEK та NUMBER_GROUPING тепер зберігаються як цілі числа у висновках JavaScript та JSON i18n.
- assertNumQueries() тепер ігнорує запити на конфігурацію з'єднання. Раніше, якщо тест було відкрито нове з'єднання з базою даних, ці запити могли бути включені як частина countNumQueries() .
- Розмір за замовчуванням тестового табличного простору Oracle збільшується з 20M до 50M, а розмір автоекстенду за замовчуванням збільшується з 10M до 25M.
- Щоб підвищити продуктивність при потоковій передачі великих наборів результатів з бази даних, QuerySet.iterator() тепер отримує 2000 рядків за раз, а не 100. Стару поведінку можна відновити за допомогою параметра chunk_size . Наприклад:
Book.objects.iterator(chunk_size=100)
- Надання невідомих імен пакетів в аргументі пакетів у поданні JavaScriptCatalog тепер викликає ValueError замість мовчання.
- Первинний ключ екземпляра моделі тепер з'являється у методі моделі . str () за промовчанням, наприклад. Об'єкт питання (1).
- makemigrations тепер виявляє зміни в полі limit_choices_to параметра моделі. Додайте це до своїх існуючих міграцій або прийміть автоматично згенеровану міграцію для полів, які її використовують.
- Виконання запитів, що потребують автоматичних просторових перетворень, тепер викликає NotImplementedError для MySQL замість мовчання з використанням не трансформованих геометрій.
- django.core.exceptions.DjangoRuntimeWarning видаляється. Він використовувався тільки в кеш-пам'яті як проміжний клас у наслідуванні CacheKeyWarning для RuntimeWarning .
- Перейменовано BaseExpression._output_field у поле output_field . Можливо, вам доведеться оновити вирази користувача.
- У більш старих версіях форми та форми поєднують свої медіа з віджетами Media, поєднуючи їх. Об'єднання тепер намагається зберегти відносний порядок елементів у кожному списку. MediaOrderConflictWarning видається, якщо замовлення не може бути збережене.
- django.contrib.gis.gdal.OGRException видаляється. Це був псевдонім для GDALException із Django 1.8.
- Підтримка GEOS 3.3.x відключена.
- Спосіб вибору даних для GeometryField змінено для підвищення продуктивності, а в необроблених SQL-запитах ці поля тепер мають бути загорнуті у connection.ops.select .
Функціонал, застарілий у версії 2.0
Контекстний аргумент Field.from_db_value() та Expression.convert_value()
Аргумент контексту Field.from_db_value() та Expression.convert_value() не використовується, оскільки він завжди є порожнім словником. Сигнатура обох методів тепер:
(self, value, expression, connection)
замість цього:
(self, value, expression, connection, context)
Підтримка старої сигнатури в полях і виразах користувача зберігається до Django 3.0.
Різне
- Модуль django.db.backends.postgresql_psycopg2 застарів на користь django.db.backends.postgresql . Це був псевдонім у Django 1.9. Це впливає лише на код, який імпортується безпосередньо з модуля. Параметр DATABASES , як і раніше, може використовувати 'django.db.backends.postgresql_psycopg2' , хоча ви можете спростити це, використовуючи ім'я 'django.db.backends.postgresql' , додане до Django 1.9.
- django.shortcuts.render_to_response() застарів на користь django.shortcuts.render() . render() приймає самі аргументи, крім того, що він також вимагає запиту.
- Значення DEFAULT_CONTENT_TYPE застаріло. Він не дуже добре взаємодіє зі сторонніми програмами та застарів, оскільки HTML5 в основному замінив XHTML .
- HttpRequest.xreadlines() застарів на користь ітерації на запит.
- Аргумент ключового слова field_name для QuerySet.earliest() та QuerySet.latest() застарів на користь передачі імен полів як аргументи. Напишіть .earliest('pub_date') замість .earliest(field_name = 'pub_date') .
Функціонал, видалений у версії 2.0
Також у Django 2.0 були видалені всі функції, які були позначені як застарілі у версіях 1.9 та 1.10.
Для Django рекомендую VDS-сервера хостера Timeweb .
По поводу упрощённого синтаксиса машрутизации урлов. С тем что увеличивается читабельность и довольно удобно принуждение типов бесспорно. А вот пример с архивом по годам и утверждение, что регулярные выражения как то ограничивали количество цифр, неверно - количество символов ограничивает данный конкретный шаблон, если его переписать как
то уже ничего не ограничивается. Да и как может функционал внутри построенный на регулярных выражениях быть более гибким чем регулярные выражения? Тут цель не переплюнуть регулярные выражения в функциональности, а добавить удобства и читабельности.
не отредактировал выражение. вот правильное
Это утверждение официальных разработчиков Django в release notes к данному выпуску.