Django 4.0 release notes

7 december 2021

Välkommen till Django 4.0!

Dessa release notes täcker nya funktioner, samt några bakåtkompatibla ändringar som du vill vara medveten om när du uppgraderar från Django 3.2 eller tidigare. Vi har börjat utfasningsprocessen för vissa funktioner.

Se guiden Så här uppgraderar du Django till en nyare version om du ska uppdatera ett befintligt projekt.

Kompatibilitet med Python

Django 4.0 stöder Python 3.8, 3.9 och 3.10. Vi rekommenderar starkt och stöder endast officiellt den senaste versionen av varje serie.

Django 3.2.x-serien är den sista som stöder Python 3.6 och 3.7.

Vad är nytt i Django 4.0

zoneinfo standardimplementering av tidszon

Standardbiblioteket Pythons zoneinfo är nu standardimplementeringen av tidszoner i Django.

Detta är nästa steg i migrationen från att använda pytz till att använda zoneinfo. Django 3.2 tillät användning av tidszoner som inte är pytz. Django 4.0 gör zoneinfo till standardimplementering. Stöd för pytz är nu föråldrat och kommer att tas bort i Django 5.0.

zoneinfo är en del av Pythons standardbibliotek från Python 3.9. Paketet backports.zoneinfo installeras automatiskt tillsammans med Django om du använder Python 3.8.

Övergången till zoneinfo bör vara i stort sett transparent. Val av aktuell tidszon, konvertering av datatidsinstanser till aktuell tidszon i formulär och mallar, samt operationer på medvetna datatider i UTC påverkas inte.

Men om du arbetar med tidszoner som inte är UTC och använder API:erna pytz normalize() och localize(), eventuellt med inställningen TIME_ZONE, måste du granska din kod eftersom pytz och zoneinfo inte är helt likvärdiga.

För att ge tid för en sådan granskning tillåter övergångsinställningen USE_DEPRECATED_PYTZ fortsatt användning av pytz under 4.x releasecykeln. Denna inställning kommer att tas bort i Django 5.0.

Dessutom kan ett pytz_deprecation_shim-paket, skapat av zoneinfo-författaren, användas för att hjälpa till med migreringen från pytz. Detta paket innehåller shims som hjälper dig att ta bort pytz på ett säkert sätt och har en detaljerad migreringsguide` som visar hur man flyttar till de nya zoneinfo API:erna.

Att använda pytz_deprecation_shim och övergångsinställningen USE_DEPRECATED_PYTZ rekommenderas om du behöver en gradvis uppdateringsväg.

Funktionella unika begränsningar

Det nya *expressions positionella argumentet för UniqueConstraint() gör det möjligt att skapa funktionella unika begränsningar för uttryck och databasfunktioner. Till exempel:

from django.db import models
from django.db.models import UniqueConstraint
from django.db.models.functions import Lower


class MyModel(models.Model):
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)

    class Meta:
        constraints = [
            UniqueConstraint(
                Lower("first_name"),
                Lower("last_name").desc(),
                name="first_last_name_unique",
            ),
        ]

Funktionella unika begränsningar läggs till i modeller med hjälp av alternativet Meta.constraints.

scrypt lösenord hasher

Den nya scrypt password hasher är säkrare och rekommenderas framför PBKDF2. Det är dock inte standard eftersom det kräver OpenSSL 1.1+ och mer minne.

Redis cache backend

Den nya django.core.cache.backends.redis.RedisCache cache backend ger inbyggt stöd för cachelagring med Redis. redis-py 3.0.0 eller högre krävs. För mer information, se dokumentation om cachelagring med Redis i Django.

Mallbaserad rendering av formulär

Forms, Formsets, och ErrorList renderas nu med hjälp av mallmotorn för att förbättra anpassningen. Se nya render(), get_context(), och template_name för Form och :ref:formset rendering <formset-rendering> för Formset.

Mindre funktioner

django.contrib.admin

django.contrib.admindocs

  • Admindocs tillåter nu esoteriska inställningar där ROOT_URLCONF inte är en sträng.

  • Modellavsnittet i admindocs visar nu cachelagrade egenskaper.

django.contrib.auth

  • Standardantalet iterationer för PBKDF2-lösenordshashen ökas från 260 000 till 320 000.

  • Det nya attributet LoginView.next_page och metoden get_default_redirect_url() gör det möjligt att anpassa omdirigeringen efter inloggning.

django.contrib.gis

  • Stöd för SpatiaLite 5 har lagts till.

  • GDALRaster gör det nu möjligt att skapa raster i alla virtuella GDAL-filsystem.

  • Den nya GISModelAdmin-klassen gör det möjligt att anpassa den widget som används för GeometryField. Detta uppmuntras istället för de föråldrade GeoModelAdmin och OSMGeoAdmin.

django.contrib.postgres

django.contrib.staticfiles

Cache

  • Det nya async-API:et för django.core.cache.backends.base.BaseCache påbörjar processen med att göra cache-backends async-kompatibla. De nya async-metoderna har alla namn med prefixet a, t.ex. aadd(), aget(), aset(), aget_or_set() eller adelete_many().

    I fortsättningen kommer prefixet a att användas för asynkrona varianter av metoder i allmänhet.

CSRF

Formulär

  • ModelChoiceField inkluderar nu det angivna värdet i argumentet params i ett uppkommet ValidationError för felmeddelandet invalid_choice. Detta gör att anpassade felmeddelanden kan använda platshållaren %(value)s.

  • BaseFormSet återger nu fel som inte är formulärfel med en extra klass nonform för att hjälpa till att skilja dem från formulärspecifika fel.

  • BaseFormSet gör det nu möjligt att anpassa widgeten som används när formulär raderas via can_delete genom att ställa in attributet deletion_widget eller åsidosätta metoden get_deletion_widget().

Internationalisering

  • Stöd och översättningar för det malaysiska språket har lagts till.

Generiska åsikter

  • DeleteView använder nu FormMixin, vilket gör att du kan tillhandahålla en Form-underklass, med till exempel en kryssruta, för att bekräfta radering. Dessutom gör detta att DeleteView kan fungera med django.contrib.messages.views.SuccessMessageMixin.

    I enlighet med FormMixin hanteras radering av objekt för POST-begäranden i form_valid(). Anpassad raderingslogik i delete()-hanterare bör flyttas till form_valid(), eller en delad hjälpmetod, efter behov.

Loggning

  • Aliaset för den databas som används i ett SQL-anrop skickas nu som extra kontext tillsammans med varje meddelande till loggern django.db.backends.

Kommandon för hantering

Modeller

  • Ny QuerySet.contains(obj)-metod returnerar om queryset innehåller det givna objektet. Detta försöker utföra frågan på det enklaste och snabbaste sättet som möjligt.

  • Det nya argumentet precision i databasfunktionen Round() gör det möjligt att ange antalet decimaler efter avrundning.

  • QuerySet.bulk_create() ställer nu in primärnyckeln på objekt när SQLite 3.35+ används.

  • DurationField har nu stöd för att multiplicera och dividera med skalära värden på SQLite.

  • QuerySet.bulk_update() returnerar nu antalet objekt som uppdaterats.

  • Det nya attributet Expression.empty_result_set_value gör det möjligt att ange ett värde som ska returneras när funktionen används för en tom resultatmängd.

  • Argumentet skip_locked i QuerySet.select_for_update() är nu tillåtet i MariaDB 10.6+.

  • Lookup-uttryck kan nu användas i QuerySet-annoteringar, aggregeringar och direkt i filter.

  • Det nya argumentet default för inbyggda aggregat gör det möjligt att ange ett värde som ska returneras när frågeuppsättningen (eller grupperingen) inte innehåller några poster, i stället för None.

Förfrågningar och svar

  • Klassen :~django.middleware.security.SecurityMiddleware lägger nu till rubriken Cross-Origin Opener Policy med värdet 'same-origin' för att förhindra att popup-fönster med olika ursprung delar samma webbläsarkontext. Du kan förhindra att detta huvud läggs till genom att ange inställningen SECURE_CROSS_ORIGIN_OPENER_POLICY till None.

Signaler

  • Det nya argumentet stdout för signalerna pre_migrate() och post_migrate() gör det möjligt att omdirigera utdata till ett strömliknande objekt. Det bör föredras framför sys.stdout och print() när det gäller att avge verbala utdata för att möjliggöra korrekt fångst vid testning.

Mallar

  • floatformat mallfilter tillåter nu användning av suffixet u för att tvinga fram inaktivering av lokalisering.

Tester

Bakåtkompatibla ändringar i 4.0

Databas backend API

I det här avsnittet beskrivs ändringar som kan behövas i tredjeparts databasbackends.

  • metoderna DatabaseOperations.year_lookup_bounds_for_date_field() och year_lookup_bounds_for_datetime_field() tar nu det valfria argumentet iso_year för att stödja gränser för ISO-8601 veckonumrerade år.

  • Det andra argumentet i metoderna DatabaseSchemaEditor._unique_sql() och _create_unique_sql() är nu fields istället för columns.

django.contrib.gis

  • Stöd för PostGIS 2.3 har tagits bort.

  • Stöd för GDAL 2.0 och GEOS 3.5 har tagits bort.

Tappat stöd för PostgreSQL 9.6

Uppströmsstöd för PostgreSQL 9.6 slutar i november 2021. Django 4.0 stöder PostgreSQL 10 och högre.

Dessutom ökas den minsta versionen som stöds av psycopg2 från 2.5.4 till 2.8.4, eftersom psycopg2 2.8.4 är den första utgåvan som stöder Python 3.8.

Borttaget stöd för Oracle 12.2 och 18c

Uppströmsstöd för Oracle 12.2 upphör i mars 2022 och för Oracle 18c upphör det i juni 2021. Django 3.2 kommer att stödjas fram till april 2024. Django 4.0 stöder officiellt Oracle 19c.

CSRF_TRUSTED_ORIGINS ändringar

Formatändring

Värden i inställningen CSRF_TRUSTED_ORIGINS måste innehålla schemat (t.ex. 'http://' eller 'https://') i stället för bara värdnamnet.

Dessutom måste värden som börjar med en punkt nu också innehålla en asterisk före punkten. Ändra till exempel `.example.com till 'https://*.example.com'.

En systemkontroll upptäcker eventuella nödvändiga ändringar.

Konfigurering av den kan nu krävas

Eftersom CSRF-skydd nu konsulterar rubriken Origin kan du behöva ställa in CSRF_TRUSTED_ORIGINS, särskilt om du tillåter förfrågningar från underdomäner genom att ställa in CSRF_COOKIE_DOMAIN (eller SESSION_COOKIE_DOMAIN om CSRF_USE_SESSIONS är aktiverat) till ett värde som börjar med en punkt.

SecurityMiddleware ställer inte längre in rubriken X-XSS-Protection

Klassen:~django.middleware.security.SecurityMiddleware ställer inte längre in rubriken X-XSS-Protection om inställningen SECURE_BROWSER_XSS_FILTER är True. Inställningen är borttagen.

De flesta moderna webbläsare respekterar inte HTTP-rubriken X-XSS-Protection. Du kan använda Content-Security-Policy utan att tillåta 'unsafe-inline'-skript istället.

Om du vill stödja äldre webbläsare och ställa in rubriken, använd den här raden i en anpassad middleware:

response.headers.setdefault("X-XSS-Protection", "1; mode=block")

Migrationer autodetektor förändringar

Autodetektorn för migreringar använder nu modelltillstånd i stället för modellklasser. Dessutom anger migreringsåtgärder för fälten ForeignKey och ManyToManyField inte längre attribut som inte skickades till fälten under initialiseringen.

Som en bieffekt kan körning av makemigrations generera no-op AlterField operationer för ManyToManyField och ForeignKey fält i vissa fall.

DeleteView ändringar

DeleteView använder nu FormMixin för att hantera POST-begäranden. Som en följd av detta bör all anpassad borttagningslogik i delete()-hanterare flyttas till form_valid(), eller en delad hjälpmetod, om så krävs.

Ändringar i namnschemat för tabeller och kolumner i Oracle

Django 4.0 ändrade oavsiktligt namnschemat för tabeller och kolumner på Oracle. Detta orsakar fel för modeller och fält med namn som är längre än 30 tecken. Tyvärr krävs det att vissa Oracle-tabeller och kolumner byter namn. Använd uppgraderingsskriptet i 33789 för att generera RENAME-satser för att ändra namngivningsschemat.

Diverse

  • Stöd för cx_Oracle < 7.0 har tagits bort.

  • För att möjliggöra servering av en Django-webbplats på en underväg utan att ändra värdet på STATIC_URL, tas det inledande snedstrecket bort från den inställningen (nu 'static/') i standardmallen startproject.

  • Metoden AdminSite för adminvyn index dekoreras inte längre med never_cache när den nås direkt, snarare än via den rekommenderade egenskapen AdminSite.urls eller metoden AdminSite.get_urls().

  • Operationer som inte stöds på en skivad queryset ger nu upphov till TypeError istället för AssertionError.

  • Den odokumenterade funktionen django.test.runner.reorder_suite() har bytt namn till reorder_tests(). Den accepterar nu en iterabel av tester snarare än en testsvit och returnerar en iterator av tester.

  • Anrop av FileSystemStorage.delete() med ett tomt namn ger nu upphov till ValueError istället för AssertionError.

  • Anrop av EmailMultiAlternatives.attach_alternative() eller EmailMessage.attach() med ogiltiga content eller mimetype argument ger nu upphov till ValueError istället för AssertionError.

  • assertHTMLEqual() anser inte längre att ett icke-booleskt attribut utan värde är lika med ett attribut med samma namn och värde.

  • Tester som inte laddas, t.ex. på grund av syntaxfel, matchar nu alltid när man använder test --tag.

  • Den odokumenterade funktionen django.contrib.admin.utils.lookup_needs_distinct() har bytt namn till lookup_spawns_duplicates().

  • Den odokumenterade metoden HttpRequest.get_raw_uri() tas bort. Metoden HttpRequest.build_absolute_uri() kan vara ett lämpligt alternativ.

  • Argumentet object i de odokumenterade metoderna ModelAdmin.log_addition(), log_change() och log_deletion() har bytt namn till obj.

  • RssFeed, Atom1Feed, och deras underklasser emitterar nu element utan innehåll som självstängande taggar.

  • NodeList.render() kastar inte längre utdata från render()-metoden för enskilda noder till en sträng. Node.render() bör alltid returnera en sträng som dokumenterat.

  • Egenskapen where_class i django.db.models.sql.query.Query och argumentet where_class till den privata metoden get_extra_restriction() i ForeignObject och ForeignObjectRel tas bort. Om det behövs, initiera django.db.models.sql.where.WhereNode istället.

  • Argumentet filter_clause i den odokumenterade metoden Query.add_filter() ersätts av två positionella argument filter_lhs och filter_rhs.

  • CsrfViewMiddleware använder nu request.META['CSRF_COOKIE_NEEDS_UPDATE'] i stället för request.META['CSRF_COOKIE_USED'], request.csrf_cookie_needs_reset och response.csrf_cookie_set för att spåra om CSRF-cookien ska skickas. Detta är ett odokumenterat, privat API.

  • Den odokumenterade konstanten TRANSLATOR_COMMENT_MARK flyttas från django.template.base till django.utils.translation.template.

  • Argumentet real_apps i den odokumenterade metoden django.db.migrations.state.ProjectState.__init__() måste nu vara ett set om det tillhandahålls.

  • RadioSelect och CheckboxSelectMultiple widgets återges nu i <div> taggar så att de meddelas mer koncist av skärmläsare. Om du behöver det tidigare beteendet, åsidosätt widgetmallen med lämplig mall från Django 3.2.

  • Mallfiltret floatformat är inte längre beroende av inställningen USE_L10N och returnerar alltid lokaliserad utdata. Använd suffixet u för att inaktivera lokalisering.

  • Standardvärdet för inställningen USE_L10N ändras till True. Se Lokaliseringsavsnittet ovan för mer information.

  • Som en del av flytta till zoneinfo, django.utils.timezone.utc ändras till alias datetime.timezone.utc`.

  • Den lägsta versionen av asgiref som stöds har ökats från 3.3.2 till 3.4.1.

Funktioner som inte längre är aktuella i 4.0

Användning av pytz tidszoner

Som en del av flytten till zoneinfo är användningen av tidszonerna pytz avförd.

Följaktligen är argumenten is_dst till följande också föråldrade:

Stöd för användning av pytz kommer att tas bort i Django 5.0.

Stöd för tidszoner

För att följa god praxis kommer standardvärdet för inställningen USE_TZ att ändras från False till True, och stöd för tidszoner kommer att aktiveras som standard i Django 5.0.

Observera att standardfilen settings.py som skapats av django-admin startproject innehåller USE_TZ = True sedan Django 1.4.

Du kan ställa in USE_TZ till False i dina projektinställningar innan dess för att välja bort.

Lokalisering

För att följa god praxis har standardvärdet för inställningen USE_L10N ändrats från False till True.

Dessutom är USE_L10N föråldrad från och med denna utgåva. Från och med Django 5.0 kommer som standard alla datum eller nummer som visas av Django att vara lokaliserade.

Taggen {% localize %} och filtren localize/ unlocalize kommer fortfarande att respekteras av Django.

Diverse

  • testinställningen SERIALIZE är avskriven eftersom den kan härledas från databases med alternativet :ref:serialized_rollback <test-case-serialized-rollback> aktiverat.

  • Den odokumenterade modulen django.utils.baseconv är föråldrad.

  • Den odokumenterade modulen django.utils.datetime_safe är föråldrad.

  • Standardprotokollet för webbplatskartor för webbplatskartor som byggs utanför kontexten för en begäran kommer att ändras från 'http till 'https i Django 5.0.

  • Argumentet extra_tests för DiscoverRunner.build_suite() och DiscoverRunner.run_tests() är föråldrat.

  • Aggregaten ArrayAgg, JSONBAgg och StringAgg returnerar None när det inte finns några rader istället för [], [] respektive '' i Django 5.0. Om du behöver det tidigare beteendet, ställ uttryckligen in default till Value([]), Value('[]') eller Value('').

  • Klasserna django.contrib.gis.admin.GeoModelAdmin och OSMGeoAdmin är föråldrade. Använd ModelAdmin och GISModelAdmin istället.

  • Eftersom formulärrendering nu använder mallmotorn, är den odokumenterade hjälpmetoden BaseForm._html_output() föråldrad.

  • Möjligheten att returnera en str från ErrorList och ErrorDict är föråldrad. Det förväntas att dessa metoder returnerar en SafeString.

Funktioner borttagna i 4.0

Dessa funktioner har nått slutet av sin utfasningscykel och tas bort i Django 4.0.

Se Funktioner som inte längre är aktuella i 3.0 för detaljer om dessa ändringar, inklusive hur man tar bort användningen av dessa funktioner.

  • django.utils.http.urlquote(), urlquote_plus(), urlunquote() och urlunquote_plus() tas bort.

  • django.utils.encoding.force_text() och smart_text() tas bort.

  • django.utils.translation.ugettext(), ugettext_lazy(), ugettext_noop(), ungettext() och ungettext_lazy() tas bort.

  • django.views.i18n.set_language() ställer inte in användarens språk i request.session (nyckel _language).

  • alias=None krävs i signaturen för underklasserna django.db.models.Expression.get_group_by_cols().

  • django.utils.text.unescape_entities() har tagits bort.

  • django.utils.http.is_safe_url() har tagits bort.

Se Funktioner som inte längre är aktuella i 3.1 för detaljer om dessa ändringar, inklusive hur man tar bort användningen av dessa funktioner.

  • Inställningen PASSWORD_RESET_TIMEOUT_DAYS tas bort.

  • Uppslagsfunktionen isnull tillåter inte längre att icke-booleska värden används som höger sida.

  • Undantagsklassen django.db.models.query_utils.InvalidQuery har tagits bort.

  • Ingångspunkten django-admin.py tas bort.

  • Metoden HttpRequest.is_ajax() har tagits bort.

  • Stöd för kodningsformatet före Django 3.1 för cookie-värden som används av django.contrib.messages.storage.cookie.CookieStorage har tagits bort.

  • Stöd för lösenordsåterställningstoken från före Django 3.1 på administratörssidan (som använder SHA-1-hashalgoritmen) har tagits bort.

  • Stöd för kodningsformatet för sessioner före Django 3.1 har tagits bort.

  • Stöd för signaturer från före Django 3.1 django.core.signing.Signer (kodade med SHA-1-algoritmen) har tagits bort.

  • Stöd för signaturer från före Django 3.1 django.core.signing.dumps() (kodade med SHA-1-algoritmen) i django.core.signing.loads() har tagits bort.

  • Stöd för användarsessioner före Django 3.1 (som använder SHA-1-algoritmen) har tagits bort.

  • Argumentet get_response för django.utils.deprecation.MiddlewareMixin.__init__() är obligatoriskt och accepterar inte None.

  • Argumentet providing_args för django.dispatch.Signal har tagits bort.

  • Argumentet length för django.utils.crypto.get_random_string() är obligatoriskt.

  • Meddelandet list för ModelMultipleChoiceField har tagits bort.

  • Stöd för att skicka råa kolumnaliaser till QuerySet.order_by() har tagits bort.

  • Modellfältet NullBooleanField tas bort, med undantag för stöd i historiska migreringar.

  • django.conf.urls.url() har tagits bort.

  • Modellfältet django.contrib.postgres.fields.JSONField tas bort, förutom för stöd i historiska migreringar.

  • django.contrib.postgres.fields.jsonb.KeyTransform och django.contrib.postgres.fields.jsonb.KeyTextTransform tas bort.

  • django.contrib.postgres.forms.JSONField har tagits bort.

  • Malltaggarna {% ifequal %} och {% ifnotequal %} tas bort.

  • Övergångsinställningen DEFAULT_HASHING_ALGORITHM tas bort.