Django 5.0 release notes

4 december 2023

Välkommen till Django 5.0!

Dessa release notes täcker nya funktioner, samt några bakåtkompatibla förändringar som du vill vara medveten om när du uppgraderar från Django 4.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 5.0 stöder Python 3.10, 3.11 och 3.12. Vi rekommenderar starkt och stöder endast officiellt den senaste versionen av varje serie.

Django 4.2.x-serien är den sista som stöder Python 3.8 och 3.9.

Stöd för tredjepartsbibliotek för äldre versioner av Django

Efter lanseringen av Django 5.0 föreslår vi att tredjepartsappförfattare släpper stödet för alla versioner av Django före 4.2. Vid den tidpunkten bör du kunna köra ditt pakets tester med python -Wd så att varningar om avskrivningar visas. Efter att du har åtgärdat varningarna bör din app vara kompatibel med Django 5.0.

Vad är nytt i Django 5.0

Facet-filter i administratörsgränssnittet

Facetträkningar visas nu för tillämpade filter i adminändringslistan när de växlas på via användargränssnittet. Detta beteende kan ändras via det nya attributet ModelAdmin.show_facets. För mer information se Facetter.

Förenklade mallar för rendering av formulärfält

Django 5.0 introducerar konceptet med en fältgrupp och fältgruppsmallar. Detta förenklar rendering av de relaterade elementen i ett Django-formulärsfält, såsom dess etikett, widget, hjälptext och fel.

Till exempel mallen nedan:

<form>
...
<div>
  {{ form.name.label_tag }}
  {% if form.name.help_text %}
    <div class="helptext" id="{{ form.name.auto_id }}_helptext">
      {{ form.name.help_text|safe }}
    </div>
  {% endif %}
  {{ form.name.errors }}
  {{ form.name }}
  <div class="row">
    <div class="col">
      {{ form.email.label_tag }}
      {% if form.email.help_text %}
        <div class="helptext" id="{{ form.email.auto_id }}_helptext">
          {{ form.email.help_text|safe }}
        </div>
      {% endif %}
      {{ form.email.errors }}
      {{ form.email }}
    </div>
    <div class="col">
      {{ form.password.label_tag }}
      {% if form.password.help_text %}
        <div class="helptext" id="{{ form.password.auto_id }}_helptext">
          {{ form.password.help_text|safe }}
        </div>
      {% endif %}
      {{ form.password.errors }}
      {{ form.password }}
    </div>
  </div>
</div>
...
</form>

Kan nu förenklas till:

<form>
...
<div>
  {{ form.name.as_field_group }}
  <div class="row">
    <div class="col">{{ form.email.as_field_group }}</div>
    <div class="col">{{ form.password.as_field_group }}</div>
  </div>
</div>
...
</form>

as_field_group() återger fält med mallen "django/forms/field.html" som standard och kan anpassas per projekt, per fält eller per begäran. Se Återanvändbara mallar för fältgrupper.

Databasberäknade standardvärden

Den nya parametern Field.db_default anger ett databasberäknat standardvärde. Till exempel:

from django.db import models
from django.db.models.functions import Now, Pi


class MyModel(models.Model):
    age = models.IntegerField(db_default=18)
    created = models.DateTimeField(db_default=Now())
    circumference = models.FloatField(db_default=2 * Pi())

Databasgenererat modellfält

Den nya GeneratedField gör det möjligt att skapa databasgenererade kolumner. Detta fält kan användas på alla stödda databasbackends för att skapa ett fält som alltid beräknas från andra fält. Till exempel:

from django.db import models
from django.db.models import F


class Square(models.Model):
    side = models.IntegerField()
    area = models.GeneratedField(
        expression=F("side") * F("side"),
        output_field=models.BigIntegerField(),
        db_persist=True,
    )

Fler alternativ för att deklarera fältval

Field.choices (för modellfält) och ChoiceField.choices (för formulärfält) ger mer flexibilitet när man deklarerar deras värden. I tidigare versioner av Django skulle choices antingen vara en lista med 2-tupler eller en Uppräkningstyper-underklass, men den senare krävde åtkomst till attributet .choices för att tillhandahålla värdena i den förväntade formen:

from django.db import models

Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")

SPORT_CHOICES = [
    ("Martial Arts", [("judo", "Judo"), ("karate", "Karate")]),
    ("Racket", [("badminton", "Badminton"), ("tennis", "Tennis")]),
    ("unknown", "Unknown"),
]


class Winner(models.Model):
    name = models.CharField(...)
    medal = models.CharField(..., choices=Medal.choices)
    sport = models.CharField(..., choices=SPORT_CHOICES)

Django 5.0 lägger till stöd för att acceptera en mappning eller en callable istället för en iterable, och kräver inte längre att .choices används direkt för att expandera enumerationstyper:

from django.db import models

Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")

SPORT_CHOICES = {  # Using a mapping instead of a list of 2-tuples.
    "Martial Arts": {"judo": "Judo", "karate": "Karate"},
    "Racket": {"badminton": "Badminton", "tennis": "Tennis"},
    "unknown": "Unknown",
}


def get_scores():
    return [(i, str(i)) for i in range(10)]


class Winner(models.Model):
    name = models.CharField(...)
    medal = models.CharField(..., choices=Medal)  # Using `.choices` not required.
    sport = models.CharField(..., choices=SPORT_CHOICES)
    score = models.IntegerField(choices=get_scores)  # A callable is allowed.

Under huven normaliseras de tillhandahållna valen till en lista med 2-tuples som den kanoniska formen när val-värdet uppdateras. För mer information, se modellfältets referens på choices.

Mindre funktioner

django.contrib.admin

  • Den nya metoden AdminSite.get_log_entries() gör det möjligt att anpassa frågeuppsättningen för webbplatsens listade loggposter.

  • Adminfiltren django.contrib.admin.AllValuesFieldListFilter, ChoicesFieldListFilter, RelatedFieldListFilter och RelatedOnlyFieldListFilter hanterar nu flervärdiga frågeparametrar.

  • XRegExp är uppgraderad från version 3.2.0 till 5.1.1.

  • Den nya metoden AdminSite.get_model_admin() returnerar en adminklass för den angivna modellklassen.

  • Egenskaper i ModelAdmin.list_display stöder nu attributet boolean.

  • jQuery uppgraderas från version 3.6.4 till 3.7.1.

django.contrib.auth

django.contrib.contenttypes

django.contrib.gis

  • Den nya ClosestPoint() funktionen returnerar en 2-dimensionell punkt på geometrin som är närmast en annan geometri.

  • GIS-aggregat stöder nu argumentet filter.

  • Stöd för GDAL 3.7 och GEOS 3.12 har lagts till.

  • Den nya metoden GEOSGeometry.equals_identical() möjliggör punktvis ekvivalenskontroll av geometrier.

django.contrib.messages

django.contrib.postgres

Asynkrona vyer

  • Under ASGI hanteras nu http.disconnect-händelser. Detta gör det möjligt för vyer att utföra all nödvändig upprensning om en klient kopplas bort innan svaret genereras. Se Hantering av frånkopplingar för mer information.

Dekoratörer

Felrapportering

Fil delning

  • File.open() skickar nu alla positionella (*args) och nyckelordsargument (**kwargs) till Pythons inbyggda open().

Formulär

  • Det nya argumentet assume_scheme för URLField gör det möjligt att ange ett standard URL-schema.

  • För att förbättra tillgängligheten har följande ändringar gjorts:

    • Formulärfält innehåller nu HTML-attributet aria-describedby för att skärmläsare ska kunna associera formulärfält med hjälptexten.

    • Ogiltiga formulärfält innehåller nu HTML-attributet aria-invalid="true".

Internationalisering

  • Support och översättningar för språket uigur finns nu tillgängliga.

Migreringar

Modeller

Sidindelning

Signaler

  • De nya metoderna Signal.asend() och Signal.asend_robust() tillåter asynkron signalutskick. Signalmottagare kan vara synkrona eller asynkrona och kommer automatiskt att anpassas till rätt anropsstil.

Mallar

  • Det nya mallfiltret escapeseq tillämpar escape på varje element i en sekvens.

Tester

Validerare

  • Det nya argumentet offset i StepValueValidator gör det möjligt att ange en offset för giltiga värden.

Bakåtkompatibla ändringar i 5.0

Databas backend API

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

  • DatabaseFeatures.supports_expression_defaults bör sättas till False om databasen inte stöder användning av databasfunktioner som standardvärden.

  • DatabaseFeatures.supports_default_keyword_in_insert bör sättas till False om databasen inte stöder nyckelordet DEFAULT i INSERT-frågor.

  • DatabaseFeatures.supports_default_keyword_in_bulk_insert bör sättas till False om databasen inte stöder nyckelordet DEFAULT i bulkfrågor INSERT.

django.contrib.gis

  • Stöd för GDAL 2.2 och 2.3 har tagits bort.

  • Stöd för GEOS 3.6 och 3.7 har tagits bort.

django.contrib.sitemaps

  • Funktionen django.contrib.sitemaps.ping_google() och hanteringskommandot ping_google tas bort eftersom slutpunkten för Google Sitemaps ping är föråldrad och kommer att tas bort i januari 2024.

  • Undantagsklassen django.contrib.sitemaps.SitemapNotFound tas bort.

Borttaget stöd för MySQL < 8.0.11

Stöd för tidigare utgåvor av MySQL 8.0.x-serien har tagits bort. Django 5.0 stöder MySQL 8.0.11 och högre.

Användning av create_defaults__exact kan nu krävas med QuerySet.update_or_create()

QuerySet.update_or_create() har nu stöd för parametern create_defaults. Som en följd av detta bör alla modeller som har ett fält med namnet create_defaults som används med en update_or_create() specificera fältet i uppslagningen med create_defaults__exact.

Migrering av befintliga UUIDField på MariaDB 10.7+

På MariaDB 10.7+ skapas nu UUIDField som UUID-kolumn snarare än CHAR(32)-kolumn. Som en följd av detta bör alla UUIDField som skapats i Django < 5.0 ersättas med en UUIDField underklass som stöds av CHAR(32):

class Char32UUIDField(models.UUIDField):
    def db_type(self, connection):
        return "char(32)"

    def get_db_prep_value(self, value, connection, prepared=False):
        value = super().get_db_prep_value(value, connection, prepared)
        if value is not None:
            value = value.hex
        return value

Till exempel:

class MyModel(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)

Bör bli:

class Char32UUIDField(models.UUIDField): ...


class MyModel(models.Model):
    uuid = Char32UUIDField(primary_key=True, default=uuid.uuid4)

Om du kör kommandot makemigrations genereras en migrering som innehåller en ”AlterField”-operation utan undantag.

Diverse

  • Argumentet instance i den odokumenterade metoden BaseModelFormSet.save_existing() har bytt namn till obj.

  • Den odokumenterade django.contrib.admin.helpers.checkbox är borttagen.

  • Heltalsfält valideras nu som 64-bitars heltal i SQLite för att matcha beteendet i sqlite3.

  • Det odokumenterade attributet Query.annotation_select_mask ändras från en uppsättning strängar till en ordnad lista med strängar.

  • ImageField.update_dimension_fields() anropas inte längre på signalen post_init om width_field och height_field inte är inställda.

  • Now databasfunktion använder nu LOCALTIMESTAMP istället för CURRENT_TIMESTAMP på Oracle.

  • AdminSite.site_header återges nu i en <div> tagg istället för <h1>. Skärmläsaranvändare förlitar sig på rubrikelement för navigering på en sida. Att ha två <h1>-element var förvirrande och webbplatsrubriken var inte till hjälp eftersom den upprepas på alla sidor.

  • För att förbättra tillgängligheten återges nu admins huvudinnehållsyta och rubrikinnehållsyta i taggarna <main> och <header> istället för <div>.

  • I databaser utan inbyggt stöd för SQL-operatorn XOR returnerar nu ^ som operatorn exklusivt eller (XOR) rader som matchas av ett udda antal operander i stället för exakt en operand. Detta överensstämmer med beteendet i MySQL, MariaDB och Python.

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

  • Den lägsta versionen av Selenium som stöds har ökats från 3.8.0 till 4.8.0.

  • Undantagen AlreadyRegistered och NotRegistered flyttas från django.contrib.admin.sites till django.contrib.admin.exceptions.

  • Den lägsta versionen av SQLite som stöds har ökats från 3.21.0 till 3.27.0.

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

  • Om SQL-frågor körs innan appregistret har fyllts på helt utlöses nu RuntimeWarning.

  • BadRequest uppstår för icke-UTF-8-kodade förfrågningar med innehållstypen application/x-www-form-urlencoded. Se RFC 1866 för mer information.

  • Den minsta versionen av colorama som stöds har ökats till 0.4.6.

  • Den minsta versionen av docutils som stöds har ökats till 0.19.

  • Filtrering av querysets mot överflödiga heltalsvärden returnerar nu alltid en tom queryset. Som en följd av detta kan du behöva använda ExpressionWrapper() för att :ref:``explicit omsluta <using-f-with-annotations>` aritmetik mot heltalsfält i sådana fall.

Funktioner som inte längre är aktuella i 5.0

Diverse

  • Renderingarna DjangoDivFormRenderer och Jinja2DivFormRenderer för övergångsformer är föråldrade.

  • Att skicka positionella argument name och violation_error_message till BaseConstraint är föråldrat till förmån för argument med endast nyckelord.

  • request läggs till i signaturen för ModelAdmin.lookup_allowed(). Stöd för ModelAdmin subklasser som inte accepterar detta argument är föråldrat.

  • Metoden get_joining_columns() för ForeignObject och ForeignObjectRel är föråldrad. Från och med Django 6.0 kommer django.db.models.sql.datastructures.Join inte längre att fallbacka till get_joining_columns(). Underklasser bör implementera get_joining_fields() istället.

  • Metoden ForeignObject.get_reverse_joining_columns() är föråldrad.

  • Standardschemat för forms.URLField kommer att ändras från "http" till "https" i Django 6.0. Ställ in FORMS_URLFIELD_ASSUME_HTTPS övergångsinställning till True för att välja att anta "https" under Django 5.x utgivningscykel.

  • FORMS_URLFIELD_ASSUME_HTTPS övergångsinställning är föråldrad.

  • Stöd för att anropa format_html() utan att skicka args eller kwargs kommer att tas bort.

  • Stöd för cx_Oracle är borttaget till förmån för oracledb 1.3.2+ Python-drivrutin.

  • DatabaseOperations.field_cast_sql() är föråldrad till förmån för DatabaseOperations.lookup_cast(). Från och med Django 6.0 kommer BuiltinLookup.process_lhs() inte längre att anropa field_cast_sql(). Tredjeparts databas backends bör implementera lookup_cast() istället.

  • Metaklassen django.db.models.enums.ChoicesMeta har bytt namn till ChoicesType.

  • Metoden Prefetch.get_current_queryset() är föråldrad.

  • Metoden get_prefetch_queryset() för relaterade hanterare och beskrivare är föråldrad. Från och med Django 6.0 kommer get_prefetcher() och prefetch_related_objects() inte längre att fallbacka till get_prefetch_queryset(). Underklasser bör implementera get_prefetch_querysets() istället.

Funktioner borttagna i 5.0

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

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

  • Testinställningen SERIALIZE har tagits bort.

  • Den odokumenterade modulen django.utils.baseconv tas bort.

  • Den odokumenterade modulen django.utils.datetime_safe tas bort.

  • Standardvärdet för inställningen USE_TZ ändras från False till True.

  • Standardprotokollet för webbplatskartor som byggs upp utanför en begäran ändras från 'http till 'https.

  • Argumentet extra_tests för DiscoverRunner.build_suite() och DiscoverRunner.run_tests() har tagits bort.

  • Aggregaten django.contrib.postgres.aggregates.ArrayAgg, JSONBAgg och StringAgg returnerar inte längre [], [] respektive '' när det inte finns några rader.

  • Inställningen USE_L10N har tagits bort.

  • Övergångsinställningen USE_DEPRECATED_PYTZ har tagits bort.

  • Stöd för tidszoner av typen pytz har tagits bort.

  • Argumentet is_dst tas bort från:

    • QuerySet.datetimes()

    • django.utils.timezone.make_aware()`

    • django.db.models.functions.Trunc()`

    • django.db.models.functions.TruncSecond()`

    • django.db.models.functions.TruncMinute()

    • django.db.models.functions.TruncHour()`

    • django.db.models.functions.TruncDay()`

    • django.db.models.functions.TruncWeek()

    • django.db.models.functions.TruncMonth()

    • django.db.models.functions.TruncQuarter()`

    • django.db.models.functions.TruncYear()`

  • Klasserna django.contrib.gis.admin.GeoModelAdmin och OSMGeoAdmin tas bort.

  • Den odokumenterade metoden BaseForm._html_output() har tagits bort.

  • Möjligheten att returnera en str, snarare än en SafeString, vid rendering av en ErrorDict och ErrorList har tagits bort.

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

  • Metoden SitemapIndexItem.__str__() har tagits bort.

  • Övergångsinställningen CSRF_COOKIE_MASKED tas bort.

  • Argumentet name i django.utils.functional.cached_property() tas bort.

  • Argumentet opclasses i django.contrib.postgres.constraints.ExclusionConstraint har tagits bort.

  • Den odokumenterade möjligheten att skicka errors=None till SimpleTestCase.assertFormError() och assertFormsetError() har tagits bort.

  • django.contrib.sessions.serializers.PickleSerializer har tagits bort.

  • Det är inte längre tillåtet att använda QuerySet.iterator() på en queryset som hämtar relaterade objekt utan att ange argumentet chunk_size.

  • Det är inte längre tillåtet att skicka osparade modellinstanser till relaterade filter.

  • created=True krävs i signaturen för RemoteUserBackend.configure_user() subklasser.

  • Stöd för utloggning via GET-förfrågningar i django.contrib.auth.views.LogoutView och django.contrib.auth.views.logout_then_login() tas bort.

  • Aliaset django.utils.timezone.utc till datetime.timezone.utc har tagits bort.

  • Det är inte längre tillåtet att skicka ett svarsobjekt och ett namn på ett formulär/formset till SimpleTestCase.assertFormError() och assertFormSetError().

  • django.contrib.gis.admin.OpenLayersWidget tas bort.

  • django.contrib.auth.hashers.CryptPasswordHasher tas bort.

  • Mallarna "django/forms/default.html" och "django/forms/formsets/default.html" tas bort.

  • Standardrenderingsstilen för formulär och formset ändras till div-baserad.

  • Det är inte längre tillåtet att skicka nulls_first=False eller nulls_last=False till metoderna Expression.asc() och Expression.desc() och uttrycket OrderBy.