Django 1.6 release notes

Observera

Tillägnad Malcolm Tredinnick

Den 17 mars 2013 förlorade Djangoprojektet och den fria programvarugemenskapen en mycket kär vän och utvecklare.

Malcolm var en långvarig bidragsgivare till Django, en föredömlig medlem av communityt, ett briljant sinne och en vän. Hans bidrag till Django - och till många andra projekt med öppen källkod - är nästan omöjliga att räkna upp. Många i Djangos kärnteam fick sina första patchar granskade av honom; hans mentorskap berikade oss. Hans omtanke, tålamod och hängivenhet kommer alltid att vara en inspiration för oss.

Denna version av Django är för Malcolm.

– Django-utvecklarna

6 november 2013

Välkommen till Django 1.6!

Dessa release notes täcker nya funktioner, samt några bakåtkompatibla ändringar som du bör vara medveten om när du uppgraderar från Django 1.5 eller äldre versioner. Vi har också tagit bort några funktioner, som beskrivs i vår utfasningsplan, och vi har börjat utfasningsprocessen för vissa funktioner.

Kompatibilitet med Python

Django 1.6, precis som Django 1.5, kräver Python 2.6.5 eller senare. Python 3 stöds också officiellt. Vi rekommenderar starkt den senaste mindre utgåvan för varje Python-serie som stöds (2.6.X, 2.7.X, 3.2.X och 3.3.X).

Django 1.6 kommer att vara den sista utgåvan som stöder Python 2.6; från och med Django 1.7 kommer den minsta Python-versionen som stöds att vara 2.7.

Python 3.4 stöds inte, men stöd kommer att läggas till i Django 1.7.

Vad är nytt i Django 1.6

Förenklade standardmallar för projekt och appar

De standardmallar som används av startproject och startapp har förenklats och moderniserats. Ramverket admin är nu aktiverat som standard i nya projekt; ramverket sites är det inte längre. Ramverket clickjacking prevention är nu aktiverat och databasen använder SQLite som standard.

Om standardmallarna inte passar din smak kan du använda :ref:``anpassade projekt- och appmallar <custom-app-and-project-templates>`.

Förbättrad transaktionshantering

Djangos transaktionshantering har setts över. Autocommit på databasnivå är nu aktiverat som standard. Detta gör transaktionshanteringen mer explicit och bör förbättra prestandan. De befintliga API:erna utrangerades och nya API:er infördes, enligt beskrivningen i transaktionshanteringsdokument.

Beständiga databasanslutningar

Django har nu stöd för att återanvända samma databasanslutning för flera förfrågningar. Detta undviker omkostnaderna för att återupprätta en anslutning i början av varje begäran. För bakåtkompatibilitet är den här funktionen inaktiverad som standard. Se Beständiga anslutningar för detaljer.

Upptäckt av tester i valfri testmodul

Django 1.6 levereras med en ny testlöpare som tillåter mer flexibilitet i placeringen av tester. Den tidigare löparen (django.test.simple.DjangoTestSuiteRunner) hittade bara tester i modulerna models.py och tests.py i ett Python-paket i INSTALLED_APPS.

Den nya löparen (django.test.runner.DiscoverRunner) använder de testupptäcktsfunktioner som är inbyggda i unittest2 (versionen av unittest i Python 2.7+ standardbiblioteket och levereras med Django). Med testupptäckt kan tester placeras i vilken modul som helst vars namn matchar mönstret test*.py.

Dessutom måste de testetiketter som tillhandahålls till ./manage.py test för att nominera specifika tester att köra nu vara fullständiga Python-punktade sökvägar (eller katalogsökvägar), snarare än applabel.TestCase.test_method_name pseudosökvägar. Detta gör det möjligt att köra tester var som helst i din kodbas, snarare än bara i INSTALLED_APPS. För mer information, se Testning i Django.

Denna ändring är bakåtkompatibel; se :ref:``backwards-incompatibility notes<new-test-runner>`.

Aggregering med hänsyn till tidszon

Stödet för tidszoner som infördes i Django 1.4 fungerade inte bra med QuerySet.dates(): aggregering utfördes alltid i UTC. Denna begränsning upphävdes i Django 1.6. Använd QuerySet.datetimes() för att utföra tidszonmedveten aggregering på en DateTimeField.

Stöd för sparpunkter i SQLite

Django 1.6 lägger till stöd för sparpunkter i SQLite, med vissa begränsningar.

modellfältet BinaryField

Ett nytt django.db.models.BinaryField modellfält tillåter lagring av rå binär data i databasen.

Widgets för GeoDjango-formulär

GeoDjango tillhandahåller nu formfält och widgets för sina geospecialiserade fält. De är OpenLayers-baserade som standard, men de kan anpassas för att använda något annat JS-ramverk.

kommandot check har lagts till för att verifiera kompatibilitet

Ett check-hanteringskommando har lagts till, så att du kan kontrollera om din aktuella konfiguration (för närvarande inriktad på inställningar) är kompatibel med den aktuella versionen av Django.

Model.save() algoritm ändrad

Metoden Model.save() försöker nu att direkt UPDATE databasen om instansen har ett primärnyckelvärde. Tidigare utfördes SELECT för att avgöra om UPDATE eller INSERT behövdes. Den nya algoritmen behöver bara en fråga för att uppdatera en befintlig rad medan den gamla algoritmen behövde två. Se Model.save() för mer information.

I vissa sällsynta fall rapporterar databasen inte att en matchande rad hittades när du gör en `` UPPDATERING``. Ett exempel är PostgreSQL ON UPDATE trigger som returnerar NULL. I sådana fall är det möjligt att ställa in django.db.models.Options.select_on_save-flaggan för att tvinga sparandet att använda den gamla algoritmen.

Mindre funktioner

  • Autentiseringsbackends kan höja PermissionDenied för att omedelbart misslyckas med autentiseringskedjan.

  • Flaggan HttpOnly kan ställas in på CSRF-cookien med CSRF_COOKIE_HTTPONLY.

  • assertQuerysetEqual() kontrollerar nu för odefinierad ordning och ger upphov till ValueError om odefinierad ordning upptäcks. Ordningen ses som odefinierad om den givna QuerySet inte är ordnad och det finns mer än ett ordnat värde att jämföra mot.

  • Lagt till earliest() för symmetri med latest().

  • Förutom year, month och day stöder ORM nu även hour, minute och second.

  • Django omsluter nu alla PEP 249 undantag.

  • Standardwidgetarna för EmailField, URLField, IntegerField, FloatField och DecimalField använder de nya typattributen som finns tillgängliga i HTML5 (type='email', type='url', type='number'). Observera att på grund av oregelbundet stöd för inmatningstypen number med lokaliserade siffror i nuvarande webbläsare, använder Django den endast när numeriska fält inte är lokaliserade.

  • Argumentet number för :ref:lazy plural translations <lazy-plural-translations> kan anges vid översättningstidpunkten snarare än vid definitionstidpunkten.

  • För anpassade hanteringskommandon: Verifiering av giltiga inställningar i kommandon som begär det med hjälp av det interna alternativet BaseCommand.can_import_settings utförs nu oberoende av hanteringen av den lokala inställningen som ska vara aktiv när kommandot körs. Det senare kan nu påverkas av det nya interna alternativet BaseCommand.leave_locale_alone. Se Hanteringskommandon och lokala språk för mer information.

  • success_url i DeletionMixin interpoleras nu med dess objekts` ``__dict__.

  • HttpResponseRedirect och HttpResponsePermanentRedirect tillhandahåller nu ett url-attribut (motsvarande URL:en som svaret kommer att omdirigeras till).

  • Cachebackend MemcachedCache använder nu det senaste pickle-protokollet som finns tillgängligt.

  • Lagt till SuccessMessageMixin som tillhandahåller ett uccess_message-attribut för FormView-baserade klasser.

  • Lagt till alternativen django.db.models.ForeignKey.db_constraint och django.db.models.ManyToManyField.db_constraint.

  • Det jQuery-bibliotek som är inbäddat i admin har uppgraderats till version 1.9.1.

  • Syndikeringsflöden (django.contrib.syndication) kan nu skicka extra kontext till flödesmallar med hjälp av en ny Feed.get_context_data() callback.

  • Kolumnerna i adminlistan har en klass column-<field_name> i HTML så att kolumnrubriken kan stylas med CSS, t.ex. för att ange en kolumnbredd.

  • isoleringsnivå kan anpassas under PostgreSQL.

  • Malltaggen blocktrans respekterar nu TEMPLATE_STRING_IF_INVALID för variabler som inte finns i sammanhanget, precis som andra mallkonstruktioner.

  • SimpleLazyObject kommer nu att presentera mer användbara representationer i felsökningssituationer i skalet.

  • Generic GeometryField är nu redigerbar med OpenLayers-widgeten i admin.

  • Dokumentationen innehåller en checklista för distribution.

  • Kommandot diffsettings har fått ett alternativ --all.

  • django.forms.fields.Field.__init__ anropar nu super(), vilket gör det möjligt för fältmixins att implementera __init__()-metoder som kommer att anropas på ett tillförlitligt sätt.

  • Parametern validate_max lades till i BaseFormSet och formset_factory(), och ModelForm och inline-versioner av desamma. Valideringsbeteendet för formuläruppsättningar med max_num har förtydligats. Det tidigare odokumenterade beteendet som härdade formuläruppsättningar mot minnesutmattningsattacker dokumenterades, och den odokumenterade gränsen för det högsta av 1000 eller max_num formulär ändrades så att det alltid är 1000 mer än max_num.

  • Lagt till BCryptSHA256PasswordHasher för att lösa problemet med trunkering av lösenord med bcrypt.

  • Pillow är nu det föredragna bildmanipuleringsbiblioteket att använda med Django. PIL är i väntan på utfasning (stöd kommer att tas bort i Django 1.8). För att uppgradera bör du först avinstallera PIL och därefter installera Pillow.

  • ModelForm accepterar flera nya Meta alternativ.

    • Fält som ingår i listan localized_fields kommer att lokaliseras (genom att ställa in localize på formulärfältet).

    • Alternativen labels, help_texts och error_messages kan användas för att anpassa standardfälten, se Åsidosätta standardfälten för mer information.

  • Argumentet choices till modellfält accepterar nu en iterabel av iterabler i stället för att kräva en iterabel av listor eller tupler.

  • Orsaksfrasen kan anpassas i HTTP-svar med hjälp av reason_phrase.

  • När du anger webbadressen till nästa sida för django.contrib.auth.views.logout(), django.contrib.auth.views.password_reset(), django.contrib.auth.views.password_reset_confirm() och django.contrib.auth.views.password_change() kan du nu ange URL-namn och de kommer att lösas upp.

  • Det nya alternativet dumpdata --pks anger primärnycklarna för de objekt som ska dumpas. Detta alternativ kan endast användas med en modell.

  • Lagt till QuerySet metoderna first() och last() som är bekvämlighetsmetoder som returnerar det första eller sista objektet som matchar filtren. Returnerar None om det inte finns några objekt som matchar.

  • View och RedirectView stöder nu HTTP-metoden PATCH.

  • GenericForeignKey tar nu ett valfritt for_concrete_model argument, som när det är inställt på False tillåter fältet att referera till proxy-modeller. Standardvärdet är True för att behålla det gamla beteendet.

  • Klassen:~django.middleware.locale.LocaleMiddleware lagrar nu det aktiva språket i sessionen om det inte redan finns där. Detta förhindrar förlust av språkinställningar efter sessionspolning, t.ex. utloggning.

  • SuspiciousOperation har delats upp i ett antal underklasser, och var och en kommer att loggas till en matchande namngiven logger under django.security loggningshierarkin. Tillsammans med denna förändring används en handler400 mekanism och standardvy när en SuspiciousOperation når WSGI-handlaren för att returnera en HttpResponseBadRequest.

  • Undantaget DoesNotExist innehåller nu ett meddelande som anger namnet på det attribut som används för uppslagningen.

  • Metoden get_or_create() kräver inte längre minst ett nyckelordsargument.

  • Klassen SimpleTestCase innehåller en ny assertion-hjälpare för att testa formulärfel: django.test.SimpleTestCase.assertFormsetError().

  • Listan över relaterade fält som läggs till i en QuerySet av select_related() kan rensas med select_related(None).

  • Metoderna get_extra() och get_max_num()InlineModelAdmin kan åsidosättas för att anpassa det extra och maximala antalet inline-formulär.

  • Formset har nu en total_error_count()-metod.

  • ModelForm-fält kan nu åsidosätta felmeddelanden som definieras i modellfält genom att använda error_messages-argumentet i en Field-konstruktör. För att dra nytta av den här nya funktionen med dina anpassade fält, :ref:se den uppdaterade rekommendationen <raising-validation-error> för att skapa ett ValidationError.

  • ModelAdmin bevarar nu filter i listvyn efter att ett objekt har skapats, redigerats eller tagits bort. Det är möjligt att återställa det tidigare beteendet att rensa filter genom att ställa in attributet preserve_filters till False.

  • Lagt till FormMixin.get_prefix (som returnerar FormMixin.prefix som standard) för att möjliggöra anpassning av prefix för formuläret.

  • Råa frågor (Manager.raw() eller cursor.execute()) kan nu använda parameterstilen ”pyformat”, där platshållare i frågan ges som '%(name)s' och parametrarna skickas som en ordbok snarare än en lista (utom på SQLite). Detta har länge varit möjligt (men inte officiellt stöds) på MySQL och PostgreSQL, och är nu också tillgängligt på Oracle.

  • Standardantalet iterationer för PBKDF2-lösenordshasher har ökats med 20%. Denna bakåtkompatibla ändring kommer inte att påverka befintliga lösenord eller användare som har underklassat django.contrib.auth.hashers.PBKDF2PasswordHasher för att ändra standardvärdet. Lösenord :ref:` kommer att uppgraderas <password-upgrades>` för att använda det nya iterationsantalet vid behov.

Bakåtkompatibla ändringar i 1.6

Varning

Utöver de ändringar som beskrivs i det här avsnittet bör du granska deprecation plan för alla funktioner som har tagits bort. Om du inte har uppdaterat din kod inom utfasningstiden för en viss funktion kan borttagningen av den framstå som en bakåtkompatibel ändring.

Ny modell för transaktionshantering

Förändringar i beteendet

Autocommit på databasnivå är aktiverat som standard i Django 1.6. Även om detta inte ändrar den allmänna andan i Djangos transaktionshantering, finns det några bakåtkompatibiliteter.

Sparpunkter och assertNumQueries

Ändringarna i transaktionshanteringen kan resultera i ytterligare uttalanden för att skapa, frigöra eller rulla tillbaka sparpunkter. Det är mer troligt att detta händer med SQLite, eftersom det inte hade stöd för sparpunkter förrän i den här versionen.

Om tester som använder assertNumQueries() misslyckas på grund av ett högre antal frågor än förväntat, kontrollera att de extra frågorna är relaterade till sparpunkter och justera det förväntade antalet frågor i enlighet med detta.

Alternativ för autocommit för PostgreSQL

I tidigare versioner var autocommit på databasnivå endast ett alternativ för PostgreSQL, och det inaktiverades som standard. Detta alternativ ignoreras nu och kan tas bort.

Ny testkörare

För att upprätthålla större överensstämmelse med Pythons unittest-modul stöder den nya testköraren (django.test.runner.DiscoverRunner) inte automatiskt vissa typer av tester som stöddes av den tidigare köraren:

  • Tester i filerna models.py och tests/__init__.py kommer inte längre att hittas och köras. Flytta dem till en fil vars namn börjar med test.

  • Doctests kommer inte längre att upptäckas automatiskt. För att integrera doctests i din testsvit, följ rekommendationerna i Python-dokumentationen.

Django innehåller en modifierad version av doctest-modulen från Pythons standardbibliotek (i django.test._doctest) och innehåller några ytterligare doctest-verktyg. Dessa verktyg är föråldrade och kommer att tas bort i Django 1.8; doctest-sviter bör uppdateras för att fungera med standardbibliotekets doctest-modul (eller konverteras till unittest-kompatibla tester).

Om du vill fördröja uppdateringar av din testsvit kan du ställa in din TEST_RUNNER-inställning till django.test.simple.DjangoTestSuiteRunner för att helt återställa det gamla testbeteendet. DjangoTestSuiteRunner är föråldrad men kommer inte att tas bort från Django förrän version 1.8.

Borttagning av django.contrib.gis.tests.GeoDjangoTestSuiteRunner GeoDjango anpassad testlöpare

Detta är för utvecklare som arbetar med själva GeoDjango-applikationen och relaterat till punkten ovan om ändringar i testlöparna:

Testlöparen django.contrib.gis.tests.GeoDjangoTestSuiteRunner har tagits bort och den fristående GeoDjango-testkörningsinställningen som den implementerade stöds inte längre. För att köra GeoDjango-testerna använder du helt enkelt den nya DiscoverRunner och anger appen django.contrib.gis.

Anpassade användarmodeller i tester

Införandet av den nya testköraren har också något förändrat sättet som testmodeller importeras på. Som ett resultat måste alla tester som åsidosätter AUTH_USER_MODEL för att testa beteende med en av Djangos testanvändarmodeller ( django.contrib.auth.tests.custom_user.CustomUser och django.contrib.auth.tests.custom_user.ExtensionUser) nu uttryckligen importera användarmodellen i din testmodul:

from django.contrib.auth.tests.custom_user import CustomUser


@override_settings(AUTH_USER_MODEL="auth.CustomUser")
class CustomUserFeatureTests(TestCase):
    def test_something(self):
        # Test code here
        ...

Denna import tvingar den anpassade användarmodellen att registreras. Utan denna import kommer testet inte att kunna byta in den anpassade användarmodellen och du kommer att få en felrapportering:

ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed

Tidszonmedvetna uppslagningar av dag, månad och veckodag

Django 1.6 introducerar stöd för tidszoner för day, month och week_day när USE_TZ är True. Dessa uppslagningar utfördes tidigare i UTC oavsett aktuell tidszon.

Detta kräver tidszonsdefinitioner i databasen. Om du använder SQLite måste du installera pytz. Om du använder MySQL måste du installera pytz och ladda tidszontabellerna med mysql_tzinfo_to_sql.

Tillägg av QuerySet.datetimes()

När time zone support som lades till i Django 1.4 var aktivt gav QuerySet.dates() oväntade resultat, eftersom aggregeringen utfördes i UTC. För att åtgärda detta introducerar Django 1.6 ett nytt API, QuerySet.datetimes(). Detta kräver några ändringar i din kod.

QuerySet.dates() returnerar datum-objekt

QuerySet.dates() returnerar nu en lista med date. Den brukade returnera en lista med datetime.

QuerySet.datetimes() returnerar en lista med datetime.

QuerySet.dates() inte längre användbar på DateTimeField

QuerySet.dates() ger upphov till ett fel om det används på DateTimeField när tidszonsstöd är aktivt. Använd QuerySet.datetimes() istället.

date_hierarchy kräver definitioner av tidszoner

Funktionen date_hierarchy i admin förlitar sig nu på QuerySet.datetimes() när den används på en DateTimeField.

Detta kräver tidszonsdefinitioner i databasen när USE_TZ är True. Learn more.

date_list i generiska vyer kräver tidszonsdefinitioner

Av samma anledning kräver åtkomst till date_list i samband med en datumbaserad generisk vy tidszonsdefinitioner i databasen när vyn är baserad på en DateTimeField och USE_TZ är True. Learn more.

Nya uppslagsord kan krocka med modellfält

Django 1.6 introducerar hour, minute och second lookups på DateTimeField. Om du hade modellfält som heter hour, minute eller second kommer de nya uppslagningarna att krocka med dina fältnamn. Lägg till en explicit exact lookup om detta är ett problem.

BooleanField har inte längre False som standard

När en BooleanField inte har en explicit default, är det implicita standardvärdet None. I tidigare versioner av Django var det False, men det representerade inte exakt avsaknaden av ett värde.

Kod som förlitar sig på att standardvärdet är False kan ge upphov till ett undantag när nya modellinstanser sparas i databasen, eftersom None inte är ett acceptabelt värde för en BooleanField. Du bör antingen ange default=False i fältdefinitionen eller se till att fältet är inställt på True eller False innan du sparar objektet.

Översättningar och kommentarer i mallar

Extrahering av översättningar efter kommentarer

Extrahering av översättningsbara bokstäver från mallar med kommandot makemessages upptäcker nu korrekt i18n-konstruktioner när de finns efter en kommentar av typen {# / #} på samma rad. T.ex:

{# A comment #}{% trans "This literal was incorrectly ignored. Not anymore" %}

Plats för översättarens kommentarer

Kommentarer för översättare i mallar som anges med {# / #} måste vara i slutet av en rad. Om de inte gör det ignoreras kommentarerna och makemessages genererar en varning. Ett exempel:

{# Translators: This is ignored #}{% trans "Translate me" %}
{{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
<h1>{% trans "Welcome" %}</h1>

Citat i reverse()

Vid omvända webbadresser tillämpade Django inte django.utils.http.urlquote på argument innan de interpolerades i URL-mönster. Denna bugg är åtgärdad i Django 1.6. Om du arbetade runt denna bugg genom att tillämpa URL-citering innan du skickar argument till reverse(), kan detta resultera i dubbelcitering. Om detta händer, ta helt enkelt bort URL-citeringen från din kod. Du kommer också att behöva ersätta specialtecken i URL:er som används i assertRedirects() med deras kodade versioner.

Lagring av IP-adresser i kommentarsappen

Kommentarsappen använder nu ett GenericIPAddressField för att lagra kommentatorernas IP-adresser, för att stödja kommentarer som skickas från IPv6-adresser. Hittills har de lagrats i en ”IPAddressField”, som endast är avsedd att stödja IPv4. När du sparar en kommentar från en IPv6-adress skulle adressen trunkeras i tysthet i MySQL-databaser och ge upphov till ett undantag i Oracle. Du måste ändra kolumntypen i din databas för att dra nytta av den här ändringen.

För MySQL kör du den här frågan på projektets databas:

ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);

För Oracle, kör den här frågan:

ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));

Om du inte tillämpar den här ändringen är beteendet oförändrat: på MySQL trunkeras IPv6-adresser tyst; på Oracle genereras ett undantag. Ingen databasändring behövs för SQLite- eller PostgreSQL-databaser.

Procentenheter i cursor.execute-frågor

När du kör råa SQL-frågor genom metoden cursor.execute har regeln om att dubbla procentlitteraler (%) inuti frågan förenhetligats. Tidigare berodde beteendet på databasens backend. Nu, i alla backends, behöver du bara dubbla bokstavliga procenttecken om du också tillhandahåller ersättningsparametrar. Till exempel:

# No parameters, no percent doubling
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")

# Parameters passed, non-placeholders have to be doubled
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])

SQLite-användare måste kontrollera och uppdatera sådana frågor.

Hjälptext för modellformulärsfält för ManyToManyField-fält

HTML-rendering av modellformulärfält som motsvarar ManyToManyField modellfält som används för att få den hårdkodade meningen:

Håll ned ”Control”, eller ”Command” på en Mac, för att välja mer än en.

(eller dess översättning till den aktiva språkdräkten) införs som den hjälptext som visas längs dem om varken attributen model eller form help_text specificerades av användaren (eller om denna sträng bifogades till någon help_text som tillhandahölls).

Eftersom detta skedde på modellagret fanns det inget sätt att förhindra att texten visades i fall där den inte var tillämplig, t.ex. formulärfält som implementerar användarinteraktioner som inte involverar ett tangentbord och/eller en mus.

Från och med Django 1.6, som en tillfällig bestämmelse om bakåtkompatibilitet, har logiken för att lägga till meningen ”Håll ner…” flyttats till fältlagret för modellformulär och ändrats för att lägga till texten endast när den associerade widgeten är SelectMultiple eller valda underklasser.

Ändringen kan påverka dig på ett bakåtkompatibelt sätt om du använder anpassade modellformulärsfält och/eller widgetar för modellfält av typen ManyToManyField vars användargränssnitt förlitar sig på automatisk tillhandahållande av den nämnda hårdkodade meningen. Dessa formulärfältimplementeringar måste anpassa sig till det nya scenariot genom att tillhandahålla sin egen hantering av attributet help_text.

Program som använder Django model form faciliteter tillsammans med Django inbyggda formulär fields och widgets påverkas inte men måste vara medvetna om vad som beskrivs i Ändring av hjälptexten för modellformulärsfält för ManyToManyField-fält nedan.

QuerySet iteration

QuerySet-iterationen ändrades så att alla hämtade rader omedelbart konverterades till Model-objekt. I Django 1.5 och tidigare konverterades de hämtade raderna till Model-objekt i bitar om 100.

Befintlig kod kommer att fungera, men antalet rader som konverteras till objekt kan ändras i vissa användningsfall. Sådana användningar inkluderar delvis loopning över en frågeuppsättning eller all användning som slutar med att göra __bool__ eller __contains__.

I synnerhet hämtade de flesta databasbackends alla rader på en gång redan i 1.5.

Det är fortfarande möjligt att konvertera de hämtade raderna till Model-objekt lättsamt genom att använda iterator()-metoden.

BoundField.label_tag inkluderar nu formulärets label_suffix

Detta överensstämmer med hur metoder som Form.as_p och Form.as_ul återger etiketter.

Om du manuellt renderar label_tag i dina mallar:

{{ form.my_field.label_tag }}: {{ form.my_field }}

vill du ta bort kolon (eller vilken annan separator du än använder) för att undvika att duplicera den när du uppgraderar till Django 1.6. Följande mall i Django 1.6 kommer att återges identiskt med ovanstående mall i Django 1.5, förutom att kolon kommer att visas inuti elementet <label>.

{{ form.my_field.label_tag }} {{ form.my_field }}

kommer att rendera något liknande:

<label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />

Om du vill behålla det nuvarande beteendet att rendera label_tag utan label_suffix, instansiera formuläret label_suffix=''. Du kan också anpassa label_suffix per fält med hjälp av den nya parametern label_suffixlabel_tag().

GET-parameter för administratörsvyer _changelist_filters

För att kunna bevara och återställa filter i listvyer skickar adminvyer nu runt GET-parametern _changelist_filters. Det är viktigt att du tar hänsyn till den här ändringen om du har anpassade adminmallar eller om dina tester förlitar sig på de tidigare webbadresserna. Om du vill återgå till det ursprungliga beteendet kan du ställa in attributet preserve_filters till False.

django.contrib.auth lösenordsåterställning använder bas 64-kodning av User PK

Tidigare versioner av Django använde bas 36-kodning av primärnyckeln User i vyerna och webbadresserna för återställning av lösenord (django.contrib.auth.views.password_reset_confirm()). Base 36-kodning är tillräcklig om användarens primära nyckel är ett heltal, men med införandet av anpassade användarmodeller i Django 1.5 kanske detta antagande inte längre är sant.

django.contrib.auth.views.password_reset_confirm() har ändrats för att ta en uidb64 parameter istället för uidb36. Om du vänder på den här vyn, till exempel i en anpassad mall password_reset_email.html, se till att uppdatera din kod.

En tillfällig shim för django.contrib.auth.views.password_reset_confirm() som gör det möjligt för lösenordsåterställningslänkar som genererats före Django 1.6 att fortsätta fungera har lagts till för att ge bakåtkompatibilitet; detta kommer att tas bort i Django 1.7. Så länge som din webbplats har kört Django 1.6 i mer än PASSWORD_RESET_TIMEOUT_DAYS kommer denna ändring inte att ha någon effekt. Om inte (till exempel om du uppgraderar direkt från Django 1.5 till Django 1.7), kommer alla länkar för återställning av lösenord som genereras innan du uppgraderar till Django 1.7 eller senare inte att fungera efter uppgraderingen.

Dessutom, om du har några anpassade URL:er för återställning av lösenord måste du uppdatera dem genom att ersätta uidb36 med uidb64 och bindestrecket som följer det mönstret med ett snedstreck. Lägg också till _\- i listan över tecken som kan matcha mönstret uidb64.

Till exempel:

url(
    r"^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$",
    "django.contrib.auth.views.password_reset_confirm",
    name="password_reset_confirm",
),

blir:

url(
    r"^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$",
    "django.contrib.auth.views.password_reset_confirm",
    name="password_reset_confirm",
),

Du kanske också vill lägga till shim för att stödja återställningslänkar i gammal stil. Med hjälp av exemplet ovan skulle du ändra den befintliga webbadressen genom att ersätta django.contrib.auth.views.password_reset_confirm med django.contrib.auth.views.password_reset_confirm_uidb36 och även ta bort argumentet name så att det inte står i konflikt med den nya webbadressen:

url(
    r"^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$",
    "django.contrib.auth.views.password_reset_confirm_uidb36",
),

Du kan ta bort detta URL-mönster efter att din app har distribuerats med Django 1.6 för PASSWORD_RESET_TIMEOUT_DAYS.

Standard serialisering av sessioner ändras till JSON

Historiskt sett har django.contrib.sessions använt pickle för att serialisera sessionsdata innan de lagras i backend. Om du använder signed cookie session backend och SECRET_KEY är känd av en angripare (det finns inte en inneboende sårbarhet i Django som skulle göra att den läcker), kan angriparen infoga en sträng i sessionen som, när den avplockas, exekverar godtycklig kod på servern. Tekniken för att göra detta är enkel och lätt tillgänglig på internet. Även om cookie-sessionslagringen signerar de cookie-lagrade data för att förhindra manipulering, eskalerar en SECRET_KEY-läcka omedelbart till en sårbarhet för fjärrkörning av kod.

Denna attack kan motverkas genom att serialisera sessionsdata med JSON istället för pickle. För att underlätta detta introducerade Django 1.5.3 en ny inställning, SESSION_SERIALIZER, för att anpassa sessionens serialiseringsformat. För bakåtkompatibilitet var standardinställningen att använda pickle i Django 1.5.3, men vi har ändrat standardinställningen till JSON i 1.6. Om du uppgraderar och byter från pickle till JSON kommer sessioner som skapats före uppgraderingen att gå förlorade. Även om JSON-serialisering inte stöder alla Python-objekt som pickle gör, rekommenderar vi starkt att du använder JSON-serialiserade sessioner. Var uppmärksam på följande när du kontrollerar din kod för att avgöra om JSON-serialisering fungerar för din applikation:

  • JSON kräver strängnycklar, så du kommer sannolikt att stöta på problem om du använder nycklar som inte är strängar i request.session.

  • Att ställa in sessionens utgång genom att skicka datetime-värden till set_expiry() kommer inte att fungera eftersom datetime-värden inte är serialiserbara i JSON. Du kan använda heltalsvärden istället.

Se Serialisering av session-dokumentationen för mer information.

Ändringar i Object Relational Mapper

Django 1.6 innehåller många förändringar av ORM. Dessa förändringar faller mestadels i tre kategorier:

  1. Buggfixar (t.ex. korrekta join-klausuler för generiska relationer, query combining, join promotion och join trimming)

  2. Förberedelse för nya funktioner. Till exempel är ORM nu internt redo för utländska nycklar i flera kolumner.

  3. Allmän uppstädning.

Dessa ändringar kan leda till vissa kompatibilitetsproblem. Till exempel kommer vissa frågor nu att generera olika tabellaliaser. Detta kan påverka QuerySet.extra(). Dessutom kommer vissa frågor nu att producera olika resultat. Ett exempel är exclude(condition) där villkoret är komplext (refererar till multijoins inuti Q objects). I många fall gav de berörda frågorna inte korrekta resultat i Django 1.5 men gör det nu. Tyvärr finns det också fall som ger olika resultat, men varken Django 1.5 eller 1.6 ger korrekta resultat.

Slutligen har det gjorts många ändringar i ORM:s interna API:er.

Diverse

  • django.db.models.query.EmptyQuerySet kan inte instansieras längre - den är endast användbar som en markörklass för att kontrollera om none() har anropats: isinstance(qs.none(), EmptyQuerySet)

  • Om din CSS/JavaScript-kod används för att komma åt HTML-inmatningswidgets efter typ, bör du se över den eftersom type='text'-widgets nu kan matas ut som type='email', type='url' eller type='number' beroende på deras motsvarande fälttyp.

  • Formulärfältens error_messages som innehåller en platshållare ska nu alltid använda en namngiven platshållare ("Värdet '%(value)s' är för stort" istället för "Värdet '%s' är för stort"). Se dokumentationen för motsvarande fält för mer information om namnen på platshållarna. Ändringarna i 1.6 påverkar särskilt DecimalField och ModelMultipleChoiceField.

  • Vissa error_messages för IntegerField, EmailField, IPAddressField, GenericIPAddressField och SlugField har undertryckts eftersom de duplicerade felmeddelanden som redan tillhandahålls av validerare knutna till fälten.

  • På grund av en förändring i arbetsflödet för formulärvalidering bör metoden TypedChoiceField coerce alltid returnera ett värde som finns i fältattributet choices. Denna begränsning bör lyftas igen i Django 1.7.

  • Det har skett förändringar i hur timeouts hanteras i cache-backends. Att explicit skicka in timeout=None resulterar inte längre i att standardtimeouten används. Det kommer nu att ställa in en timeout som inte löper ut. Om 0 anges i memcache-backend används inte längre standardtimeouten, utan värdet kommer nu att ställas in och upphöra omedelbart.

  • Appen django.contrib.flatpages brukade ställa in anpassade HTTP-rubriker för felsökningsändamål. Denna funktionalitet var inte dokumenterad och gjorde cachelagring ineffektiv så den har tagits bort, tillsammans med dess generiska implementering, tidigare tillgänglig i django.core.xheaders.

  • XViewMiddleware har flyttats från django.middleware.doc till django.contrib.admindocs.middleware eftersom det är en implementationsdetalj av admindocs, som visat sig inte vara återanvändbar i allmänhet.

  • GenericIPAddressField tillåter nu endast blank-värden om null-värden också är tillåtna. Att skapa en GenericIPAddressField där blank är tillåtet men null inte är det kommer att utlösa ett modellvalideringsfel eftersom blank-värden alltid lagras som null. Tidigare kunde lagring av ett blank-värde i ett fält som inte tillät null orsaka ett databasundantag vid körning.

  • Om ett NoReverseMatch-undantag uppstår från en metod vid rendering av en mall, tystas det inte. Till exempel kommer {{ obj.view_href }} att orsaka att mallrenderingen misslyckas om view_href() ger upphov till NoReverseMatch. Det finns ingen förändring av {% url %} taggen, den orsakar mallrendering att misslyckas som alltid när NoReverseMatch är upphöjd.

  • django.test.Client.logout() anropar nu django.contrib.auth.logout() som skickar signalen user_logged_out().

  • Authentication views är nu omvända efter namn, inte deras platser i django.contrib.auth.views. Om du använder vyerna utan ett namn bör du uppdatera dina urlpatterns för att använda django.conf.urls.url() med parametern namn. Till exempel:

    (r"^reset/done/$", "django.contrib.auth.views.password_reset_complete")
    

    blir:

    url(
        r"^reset/done/$",
        "django.contrib.auth.views.password_reset_complete",
        name="password_reset_complete",
    )
    
  • RedirectView har nu ett pattern_name-attribut som gör det möjligt att välja mål genom att vända på URL:en.

  • I Django 1.4 och 1.5 ansågs en tom sträng oavsiktligt inte vara ett giltigt lösenord. Detta innebar att set_password() skulle spara ett tomt lösenord som ett oanvändbart lösenord som set_unusable_password() gör, och därmed check_password() alltid returnerade False för tomma lösenord. Detta har korrigerats i denna utgåva: tomma lösenord är nu giltiga.

  • Admin changelist_view accepterade tidigare en pop GET-parameter för att ange att den skulle visas i en popup. Denna parameter har bytt namn till _popup för att vara konsekvent med resten av admin-vyerna. Du bör uppdatera dina anpassade mallar om de använder det tidigare parameternamnet.

  • validate_email() accepterar nu e-postadresser med localhost som domän.

  • Det nya alternativet makemessages --keep-pot förhindrar att den temporära filen .pot som genereras innan filen .po skapas raderas.

  • Den odokumenterade django.core.servers.basehttp.WSGIServerException har tagits bort. Använd `socket.error som tillhandahålls av standardbiblioteket istället. Denna ändring släpptes också i Django 1.5.5.

  • Signaturen för django.views.generic.base.RedirectView.get_redirect_url() har ändrats och accepterar nu även positionella argument (*args, **kwargs). Alla icke namngivna fångade grupper kommer nu att skickas till get_redirect_url() vilket kan resultera i ett TypeError om du inte uppdaterar signaturen för din anpassade metod.

Funktioner som inte längre är aktuella i 1.6

API:er för transaktionshantering

Transaktionshanteringen reviderades helt i Django 1.6 och de nuvarande API:erna är föråldrade:

  • django.middleware.transaction.TransactionMiddleware

  • django.db.transaction.autocommit

  • django.db.transaction.commit_on_success

  • django.db.transaction.commit_manually

  • inställningen TRANSACTIONS_MANAGED

django.contrib.comments

Djangos ramverk för kommentarer har utgått och stöds inte längre. Det kommer att finnas tillgängligt i Django 1.6 och 1.7, och tas bort i Django 1.8. De flesta användare kommer att vara bättre betjänta av en anpassad lösning eller en värdprodukt som Disqus.

Koden som tidigare var känd som django.contrib.comments är fortfarande tillgänglig i ett externt arkiv.

Stöd för PostgreSQL-versioner äldre än 8.4

Slutet på uppströms stödperioder nåddes i december 2011 för PostgreSQL 8.2 och i februari 2013 för 8.3. Som en följd av detta ställer Django 1.6 8.4 som den minsta PostgreSQL-versionen som den officiellt stöder.

Du uppmuntras starkt att använda den senaste versionen av PostgreSQL som finns tillgänglig på grund av prestandaförbättringar och för att dra nytta av den inbyggda streamingreplikeringen som finns i PostgreSQL 9.x.

Ändringar av cycle och firstof

Mallsystemet escapar i allmänhet alla variabler för att undvika XSS-attacker. På grund av en historisk olyckshändelse återger dock taggarna cycle och firstof sina argument som de är.

Django 1.6 startar en process för att korrigera denna inkonsekvens. Mallbiblioteket future tillhandahåller alternativa implementationer av cycle och firstof som autoescape sina inmatningar. Om du använder dessa taggar, uppmuntras du att inkludera följande rad längst upp i dina mallar för att aktivera det nya beteendet:

{% load cycle from future %}

eller:

{% load firstof from future %}

De taggar som implementerar det gamla beteendet har utgått och i Django 1.8 kommer det gamla beteendet att ersättas med det nya beteendet. För att säkerställa kompatibilitet med framtida versioner av Django bör befintliga mallar ändras för att använda future-versionerna.

Om det behövs kan du tillfälligt inaktivera auto-escaping med mark_safe() eller {% autoescape off %}.

CACHE_MIDDLEWARE_ANONYMOUS_ONLY inställning

CacheMiddleware och UpdateCacheMiddleware brukade tillhandahålla ett sätt att cacha förfrågningar endast om de inte gjordes av en inloggad användare. Denna mekanism var i stort sett ineffektiv eftersom mellanvaran korrekt tar hänsyn till Vary: Cookie HTTP header, och denna header ställs in vid en mängd olika tillfällen, t.ex:

  • komma åt sessionen, eller

  • med hjälp av CSRF-skydd, som är aktiverat som standard, eller

  • använder ett bibliotek på klientsidan som ställer in cookies, som Google Analytics.

Detta gör att cachen fungerar effektivt per session oavsett inställningen CACHE_MIDDLEWARE_ANONYMOUS_ONLY.

_has_changed metod för widgets

Om du har definierat dina egna formulärwidgetar och definierat metoden _has_changed för en widget, bör du nu definiera denna metod för själva formulärfältet.

modul_namn modell _meta attribut

Model._meta.module_name döptes om till model_name. Trots att det är ett privat API kommer det att gå igenom en vanlig deprecation-väg.

get_(add|change|delete)_permission modell _meta metoder

metoderna Model._meta.get_(add|change|delete)_permission utrangerades. Även om de inte var en del av det offentliga API:et kommer de också att gå igenom en vanlig deprecation-väg. Du kan ersätta dem med django.contrib.auth.get_permission_codename('action', Model._meta) där 'action' är 'add', 'change' eller 'delete'.

get_query_set och liknande metoder byter namn till get_queryset

Metoder som returnerar en QuerySet såsom Manager.get_query_set eller ModelAdmin.queryset har bytt namn till get_queryset.

Om du skriver ett bibliotek som implementerar till exempel en metod Manager.get_query_set och du behöver stödja gamla Django-versioner, bör du byta namn på metoden och villkorligt lägga till ett alias med det gamla namnet:

class CustomManager(models.Manager):
    def get_queryset(self):
        pass  # ...

    if django.VERSION < (1, 6):
        get_query_set = get_queryset

    # For Django >= 1.6, models.Manager provides a get_query_set fallback
    # that emits a warning when used.

Om du skriver ett bibliotek som behöver anropa metoden get_queryset och måste stödja gamla Django-versioner, bör du skriva:

get_queryset = (
    some_manager.get_query_set
    if hasattr(some_manager, "get_query_set")
    else some_manager.get_queryset
)
return get_queryset()  # etc

I det allmänna fallet med en anpassad manager som både implementerar sin egen metod get_queryset och anropar den metoden, och behöver arbeta med äldre Django-versioner och bibliotek som inte har uppdaterats ännu, är det användbart att definiera en get_queryset_compat-metod enligt nedan och använda den internt i din manager:

class YourCustomManager(models.Manager):
    def get_queryset(self):
        return YourCustomQuerySet()  # for example

    if django.VERSION < (1, 6):
        get_query_set = get_queryset

    def active(self):  # for example
        return self.get_queryset_compat().filter(active=True)

    def get_queryset_compat(self):
        get_queryset = (
            self.get_query_set if hasattr(self, "get_query_set") else self.get_queryset
        )
        return get_queryset()

Detta hjälper till att minimera de ändringar som behövs, men fungerar också korrekt när det gäller underklasser (t.ex. RelatedManagers från Django 1.5) som kan åsidosätta antingen get_query_set eller get_queryset.

vyn shortcut och URLconf

Vyn shortcut flyttades från django.views.defaults till django.contrib.contenttypes.views strax efter 1.0-utgåvan, men den gamla platsen blev aldrig föråldrad. Detta förbiseende korrigerades i Django 1.6 och du bör nu använda den nya platsen.

URLconf django.conf.urls.shortcut var också föråldrad. Om du inkluderar den i en URLconf, ersätt helt enkelt:

(r"^prefix/", include("django.conf.urls.shortcut")),

med:

(
    r"^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$",
    "django.contrib.contenttypes.views.shortcut",
),

ModelForm utan fields eller exclude

Tidigare, om du ville att en ModelForm skulle använda alla fält i modellen, kunde du helt enkelt utelämna attributet Meta.fields, och alla fält skulle användas.

Detta kan leda till säkerhetsproblem där fält läggs till i modellen och oavsiktligt automatiskt blir redigerbara för slutanvändare. I vissa fall, särskilt med booleska fält, är det möjligt att detta problem är helt osynligt. Detta är en form av Mass assignment vulnerability.

Av denna anledning är detta beteende föråldrat och det är starkt avrått från att använda alternativet Meta.exclude. Istället bör alla fält som är avsedda att ingå i formuläret listas explicit i attributet fields.

Om detta säkerhetsproblem verkligen inte gäller i ditt fall finns det en genväg för att uttryckligen ange att alla fält ska användas - använd specialvärdet "__all__" för fields-attributet:

class MyModelForm(ModelForm):
    class Meta:
        fields = "__all__"
        model = MyModel

Om du har anpassade ModelForms som bara behöver användas i admin, finns det ett annat alternativ. Administratören har sina egna metoder för att definiera fält (fieldsets etc.), och därför är det överflödigt att lägga till en lista över fält till ModelForm. Istället kan man helt enkelt utelämna den inre klassen Meta i ModelForm, eller utelämna attributet Meta.model. Eftersom underklassen ModelAdmin vet vilken modell den är för, kan den lägga till de nödvändiga attributen för att härleda en fungerande ModelForm. Detta beteende fungerar även för tidigare Django-versioner.

UpdateView och CreateView utan explicita fält

De generiska vyerna CreateView och UpdateView, och allt annat som härrör från ModelFormMixin, är sårbara för det säkerhetsproblem som beskrivs i avsnittet ovan, eftersom de automatiskt kan skapa en ModelForm som använder alla fält för en modell.

Av denna anledning, om du använder dessa vyer för att redigera modeller, måste du också tillhandahålla attributet fields (nytt i Django 1.6), som är en lista över modellfält och fungerar på samma sätt som attributet ModelForm Meta.fields. Alternativt kan du ställa in attributet form_class till en ModelForm som uttryckligen definierar de fält som ska användas. Att definiera en subklass av UpdateView eller CreateView som ska användas med en modell men utan en explicit lista över fält är föråldrat.

Ändring av hjälptexten för modellformulärsfält för ManyToManyField-fält

All speciell hantering av attributet help_text för modellfälten ManyToManyField som utförs av standardmodell- eller modellformulärfält enligt beskrivningen i Hjälptext för modellformulärsfält för ManyToManyField-fält ovan är föråldrad och kommer att tas bort i Django 1.8.

Hjälptexten i dessa fält måste hanteras antingen av applikationer, anpassade formulärfält eller widgets, precis som med resten av modellfälttyperna.