Porta dina appar från Django 0.96 till 1.0¶
Django 1.0 bryter kompatibiliteten med 0.96 i vissa områden.
Den här guiden hjälper dig att porta 0.96-projekt och appar till 1.0. Den första delen av detta dokument innehåller de vanliga ändringar som behövs för att köra med 1.0. Om din kod fortfarande inte fungerar efter att du har gått igenom den första delen kan du läsa avsnittet Mindre vanliga ändringar för en lista över ett antal mindre vanliga kompatibilitetsproblem.
Se även
Den 1.0 release notes. Det dokumentet förklarar de nya funktionerna i 1.0 mer ingående; portningsguiden är mer inriktad på att hjälpa dig att snabbt uppdatera din kod.
Vanliga förändringar¶
I detta avsnitt beskrivs de ändringar mellan 0.96 och 1.0 som de flesta användare kommer att behöva göra.
Använd Unicode¶
Ändra stränglitteraler ('foo'
) till Unicode-litteraler (u'foo'
). Django använder nu Unicode-strängar genomgående. På de flesta ställen kommer råa strängar att fortsätta att fungera, men uppdatering till att använda Unicode-litteraler kommer att förhindra vissa obskyra problem.
Se Unicode-data för fullständig information.
Modeller¶
Vanliga ändringar i din models-fil:
Byt namn på maxlength
till max_length
¶
Byt namn på argumentet maxlength
till max_length
(detta ändrades för att vara konsekvent med formulärfält):
Ersätt __str__
med __unicode__
¶
Ersätt din modells funktion __str__
med en metod __unicode__
och se till att du använder Unicode (u'foo'
) i den metoden.
Ta bort prepopulated_from
¶
Ta bort prepopulated_from
-argumentet på modellfält. Det är inte längre giltigt och har flyttats till klassen ModelAdmin
i admin.py
. Se admin nedan för mer information om ändringar i admin.
Ta bort kärna
¶
Ta bort core
-argumentet från dina modellfält. Det är inte längre nödvändigt, eftersom motsvarande funktionalitet (en del av inline editing) hanteras annorlunda av admin-gränssnittet nu. Du behöver inte oroa dig för inline-redigering förrän du kommer till avsnittet Admin nedan. För tillfället, ta bort alla referenser till core
.
Ersätt class Admin:
med admin.py
¶
Ta bort alla dina inre class Admin
-deklarationer från dina modeller. De kommer inte att förstöra något om du låter dem vara kvar, men de kommer inte heller att göra något. För att registrera appar med administratören kommer du att flytta dessa deklarationer till en admin.py
-fil; se the admin nedan för mer information.
Se även
En bidragsgivare till djangosnippets har skrivit ett skript som söker igenom din models.py och genererar en motsvarande admin.py.
Exempel¶
Nedan följer ett exempel på filen models.py
med alla de ändringar du behöver göra:
Gammal (0.96) models.py
:
class Author(models.Model):
first_name = models.CharField(maxlength=30)
last_name = models.CharField(maxlength=30)
slug = models.CharField(maxlength=60, prepopulate_from=("first_name", "last_name"))
class Admin:
list_display = ["first_name", "last_name"]
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
Ny (1.0) models.py
:
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
slug = models.CharField(max_length=60)
def __unicode__(self):
return "%s %s" % (self.first_name, self.last_name)
Ny (1.0) admin.py
:
from django.contrib import admin
from models import Author
class AuthorAdmin(admin.ModelAdmin):
list_display = ["first_name", "last_name"]
prepopulated_fields = {"slug": ("first_name", "last_name")}
admin.site.register(Author, AuthorAdmin)
Administratören¶
En av de största förändringarna i 1.0 är den nya administratören. Djangos administrativa gränssnitt (django.contrib.admin
) har helt omarbetats; admin-definitioner är nu helt frikopplade från modelldefinitioner, ramverket har skrivits om för att använda Djangos nya formulärhanteringsbibliotek och omdesignats med tanke på utdragbarhet och anpassning.
I praktiken innebär det att du måste skriva om alla dina class Admin
-deklarationer. Du har redan sett i models ovan hur du kan ersätta din class Admin
med ett admin.site.register()
-anrop i en admin.py
-fil. Nedan följer lite mer information om hur man skriver om Admin
deklarationen till den nya syntaxen.
Använd ny inline-syntax¶
De nya edit_inline
-alternativen har alla flyttats till admin.py
. Här är ett exempel:
Gammal (0,96):
class Parent(models.Model): ...
class Child(models.Model):
parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)
Ny (1.0):
class ChildInline(admin.StackedInline):
model = Child
extra = 3
class ParentAdmin(admin.ModelAdmin):
model = Parent
inlines = [ChildInline]
admin.site.register(Parent, ParentAdmin)
Se objekt av typen ``InlineModelAdmin för mer information.
Förenkla fields
, eller använd fieldsets
¶
Den gamla syntaxen fields
var ganska förvirrande och har förenklats. Den gamla syntaxen fungerar fortfarande, men du måste använda fieldsets
istället.
Gammal (0,96):
class ModelOne(models.Model):
...
class Admin:
fields = ((None, {"fields": ("foo", "bar")}),)
class ModelTwo(models.Model):
...
class Admin:
fields = (
("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
)
Ny (1.0):
class ModelOneAdmin(admin.ModelAdmin):
fields = ("foo", "bar")
class ModelTwoAdmin(admin.ModelAdmin):
fieldsets = (
("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
)
Se även
Mer detaljerad information om ändringarna och orsakerna bakom dem finns på wikisidan NewformsAdminBranch
Den nya admin kommer med massor av nya funktioner; du kan läsa om dem i admin dokumentation.
URL:er¶
Uppdatera din root urls.py
¶
Om du använder administratörssidan måste du uppdatera din root urls.py
.
Gammal (0.96) urls.py
:
from django.conf.urls.defaults import *
urlpatterns = patterns(
"",
(r"^admin/", include("django.contrib.admin.urls")),
# ... the rest of your URLs here ...
)
Ny (1.0) urls.py
:
from django.conf.urls.defaults import *
# The next two lines enable the admin and load each admin.py file:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns(
"",
(r"^admin/(.*)", admin.site.root),
# ... the rest of your URLs here ...
)
Vyer¶
Använd django.forms
istället för newforms
¶
Ersätt django.newforms
med django.forms
– Django 1.0 bytte namn på modulen newforms
(introducerad i 0.96) till gamla vanliga forms
. Modulen oldforms
togs också bort.
Om du redan använder biblioteket newforms
och du använde vår rekommenderade syntax för import
-satser behöver du bara ändra dina importsatser.
Gammal:
from django import newforms as forms
Ny:
from django import forms
Om du använder det gamla formulärsystemet (tidigare känt som django.forms
och django.oldforms
) måste du skriva om dina formulär. Ett bra ställe att börja på är formulärdokumentation
Hantera uppladdade filer med hjälp av det nya API:et¶
Ersätt användningen av uppladdade filer - det vill säga poster i request.FILES
- som enkla ordböcker med den nya UploadedFile
. Den gamla syntaxen för ordböcker fungerar inte längre.
Alltså, i en vy som:
def my_view(request):
f = request.FILES["file_field_name"]
...
…måste du göra följande ändringar:
Gammal (0,96) |
Ny (1.0) |
---|---|
|
|
|
|
|
|
Arbeta med filfält med hjälp av det nya API:et¶
Den interna implementeringen av django.db.models.FileField
har ändrats. Ett synligt resultat av detta är att sättet du kommer åt specialattribut (URL, filnamn, bildstorlek etc.) för dessa modellfält har ändrats. Du kommer att behöva göra följande ändringar, förutsatt att din modells FileField
heter myfile
:
Gammal (0,96) |
Ny (1.0) |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Observera att attributen width
och height
endast är meningsfulla för ImageField
-fält. Mer information finns i dokumentationen model API.
Använd Paginator
istället för ObjectPaginator
¶
ObjectPaginator
i 0.96 har tagits bort och ersatts med en förbättrad version, django.core.paginator.Paginator
.
Mallar¶
Lär dig att älska autoescaping¶
Som standard HTML-eskapsätter mallsystemet nu automatiskt utdata från varje variabel. För mer information, se Automatisk HTML-escaping.
Om du vill inaktivera automatisk eskapning för en enskild variabel använder du filtret safe
:
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
Om du vill inaktivera auto-escaping för en hel mall, linda in mallen (eller bara en viss del av mallen) i taggen autoescape
:
{% autoescape off %}
... unescaped template content here ...
{% endautoescape %}
Mindre vanliga förändringar¶
Följande ändringar är mindre, mer lokala ändringar. De bör endast påverka mer avancerade användare, men det är förmodligen värt att läsa igenom listan och kontrollera din kod för dessa saker.
Signaler¶
Lägg till
**kwargs
till alla registrerade signalhanterare.Anslut, koppla från och skicka signaler via metoder på objektet
Signal
istället för via modulmetoder idjango.dispatch.dispatcher
.Ta bort all användning av avsändaralternativen
Anonymous
ochAny
; de finns inte längre. Du kan fortfarande ta emot signaler som skickas av vilken avsändare som helst genom att användasender=None
Gör alla anpassade signaler som du har deklarerat till instanser av
django.dispatch.Signal
istället för anonyma objekt.
Här är en snabb sammanfattning av de kodändringar du behöver göra:
Gammal (0,96) |
Ny (1.0) |
---|---|
|
|
|
|
|
|
|
|
|
|
Kommentarer¶
Om du använde Django 0.96:s app django.contrib.comments
måste du uppgradera till den nya kommentarsappen som introducerades i 1.0. Se uppgraderingsguiden för mer information.
Lokala smaker¶
Lokal smak från USA¶
django.contrib.localflavor.usa
har bytt namn till django.contrib.localflavor.us
. Denna förändring gjordes för att matcha namngivningsschemat för andra lokala smaker. För att migrera din kod är allt du behöver göra att ändra importen.
Sessioner¶
Få en ny sessionsnyckel¶
SessionBase.get_new_session_key()
har bytt namn till _get_new_session_key()
. get_new_session_object()
finns inte längre.
Fixturer¶
Laddning av en rad kräver inte längre save()
¶
Tidigare körde laddning av en rad automatiskt modellens save()
-metod. Detta är inte längre fallet, så alla fält (till exempel: tidsstämplar) som automatiskt fylldes i av en save()
behöver nu uttryckliga värden i alla fixturer.
Inställningar¶
Bättre undantag¶
Det gamla EnvironmentError
har delats upp i ett ImportError
när Django misslyckas med att hitta inställningsmodulen och ett RuntimeError
när du försöker konfigurera om inställningar efter att du redan har använt dem.
LOGIN_URL
har flyttats¶
Konstanten LOGIN_URL
flyttades från django.contrib.auth
till modulen settings
. Istället för att använda from django.contrib.auth import LOGIN_URL
hänvisa till settings.LOGIN_URL
.
APPEND_SLASH
-beteendet har uppdaterats¶
I 0.96, om en URL inte slutade med ett snedstreck eller hade en punkt i den sista komponenten i sökvägen, och APPEND_SLASH
var True, skulle Django omdirigera till samma URL, men med ett snedstreck i slutet. Nu kontrollerar Django för att se om mönstret utan det efterföljande snedstrecket skulle matchas av något i dina URL-mönster. Om så är fallet sker ingen omdirigering, eftersom det antas att du avsiktligt ville fånga det mönstret.
För de flesta människor kommer detta inte att kräva några ändringar. Vissa människor har dock URL-mönster som ser ut så här:
r"/some_prefix/(.*)$"
Tidigare skulle dessa mönster ha omdirigerats till att ha ett efterföljande snedstreck. Om du alltid vill ha ett snedstreck på sådana webbadresser skriver du om mönstret till:
r"/some_prefix/(.*/)$"
Mindre modellförändringar¶
Olika undantag från get()
¶
Hanterare returnerar nu ett MultipleObjectsReturned
undantag istället för AssertionError
:
Gammal (0,96):
try:
Model.objects.get(...)
except AssertionError:
handle_the_error()
Ny (1.0):
try:
Model.objects.get(...)
except Model.MultipleObjectsReturned:
handle_the_error()
LazyDate
har avfyrats¶
Hjälpklassen LazyDate
finns inte längre.
Standardfältvärden och frågeargument kan båda vara anropsbara objekt, så instanser av LazyDate
kan ersättas med en referens till datetime.datetime.now
:
Gammal (0,96):
class Article(models.Model):
title = models.CharField(maxlength=100)
published = models.DateField(default=LazyDate())
Ny (1.0):
import datetime
class Article(models.Model):
title = models.CharField(max_length=100)
published = models.DateField(default=datetime.datetime.now)
DecimalField
är ny, och FloatField
är nu en riktig float¶
Gammal (0,96):
class MyModel(models.Model):
field_name = models.FloatField(max_digits=10, decimal_places=3)
...
Ny (1.0):
class MyModel(models.Model):
field_name = models.DecimalField(max_digits=10, decimal_places=3)
...
Om du glömmer att göra denna ändring kommer du att se fel om att FloatField
inte tar ett max_digits
-attribut i __init__
, eftersom den nya FloatField
inte tar några precisionsrelaterade argument.
Om du använder MySQL eller PostgreSQL behövs inga ytterligare ändringar. Databasens kolumntyper för DecimalField
är desamma som för den gamla FloatField
.
Om du använder SQLite måste du tvinga databasen att visa de aktuella kolumnerna som decimaltyper i stället för flyttal. För att göra detta måste du ladda om dina data. Gör detta efter att du har gjort ändringen till att använda DecimalField
i din kod och uppdaterat Django-koden.
Varning
Säkerhetskopiera din databas först!
För SQLite innebär detta att du gör en kopia av den enda fil som lagrar databasen (namnet på den filen är DATABASE_NAME
i filen settings.py
).
För att uppgradera varje applikation till att använda en DecimalField
kan du göra följande och ersätta <app>
i koden nedan med varje apps namn:
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml
Anteckningar:
Det är viktigt att du kommer ihåg att använda XML-format i det första steget av den här processen. Vi utnyttjar en funktion i XML-datadumparna som gör det möjligt att porta floats till decimaler med SQLite.
I det andra steget kommer du att bli ombedd att bekräfta att du är beredd att förlora data för applikationen/applikationerna i fråga. Säg ja, så återställer vi dessa data i det tredje steget.
DecimalField
används inte i någon av de appar som levererades med Django innan denna ändring gjordes, så du behöver inte oroa dig för att utföra denna procedur för någon av Djangos standardmodeller.
Om något går fel under processen ovan är det bara att kopiera den säkerhetskopierade databasfilen över originalfilen och börja om.
Internationalisering¶
django.views.i18n.set_language()
kräver nu en POST-begäran¶
Tidigare användes en GET-begäran. Det gamla beteendet innebar att state (den locale som används för att visa webbplatsen) kunde ändras genom en GET-begäran, vilket strider mot HTTP-specifikationens rekommendationer. Kod som anropar denna vy måste se till att en POST-begäran nu görs, istället för en GET. Det innebär att du inte längre kan använda en länk för att komma åt vyn, utan du måste använda någon form av formulär (t.ex. en knapp).
_()
finns inte längre i inbyggda program¶
_()
(det anropsbara objektet vars namn är ett enda understreck) är inte längre monkeypatchat i builtins - det vill säga, det finns inte längre magiskt tillgängligt i varje modul.
Om du tidigare förlitade dig på att _()
alltid skulle finnas, bör du nu uttryckligen importera ugettext
eller ugettext_lazy
, om det är lämpligt, och alias det till _
själv:
from django.utils.translation import ugettext as _
Objekt för HTTP-begäran/-svar¶
Dictionary-åtkomst till HttpRequest
¶
objekten HttpRequest
stöder inte längre direkt åtkomst i ordboksstil; tidigare var både GET
och POST
data direkt tillgängliga på objektet HttpRequest
(t.ex. kunde du söka efter en bit formulärdata genom att använda if 'some_form_key' in request
eller genom att läsa request['some_form_key']
. Detta stöds inte längre; om du behöver tillgång till kombinerade GET
och POST
data, använd request.REQUEST
istället.
Det rekommenderas dock starkt att du alltid uttryckligen letar i lämplig ordbok efter den typ av begäran du förväntar dig att få (request.GET
eller request.POST
); att förlita sig på den kombinerade ordboken request.REQUEST
kan maskera ursprunget till inkommande data.
Tillgång till HTTPResponse
-rubriker¶
django.http.HttpResponse.headers
har bytt namn till _headers
och HttpResponse
stöder nu containment checking direkt. Så använd if header in response:
istället för if header in response.headers:
.
Generiska relationer¶
Generiska relationer har flyttats ut ur kärnan¶
De generiska relationsklasserna - GenericForeignKey
och GenericRelation
- har flyttats till modulen django.contrib.contenttypes
.
Testar¶
django.test.Client.login()
har ändrats¶
Gammal (0,96):
from django.test import Client
c = Client()
c.login("/path/to/login", "myuser", "mypassword")
Ny (1.0):
# ... same as above, but then:
c.login(username="myuser", password="mypassword")
Ledningskommandon¶
Kör kommandon för hantering från din kod¶
django.core.management
har genomgått en omfattande omarbetning.
Anrop till hanteringstjänster i din kod måste nu använda call_command
. Om du till exempel har en testkod som anropar flush och load_data:
from django.core import management
management.flush(verbosity=0, interactive=False)
management.load_data(["test_data"], verbosity=0)
…måste du ändra den här koden så att den lyder:
from django.core import management
management.call_command("flush", verbosity=0, interactive=False)
management.call_command("loaddata", "test_data", verbosity=0)
Underkommandon måste nu föregå alternativ¶
django-admin.py
och manage.py
kräver nu att underkommandon föregår alternativen. Så här är det:
$ django-admin.py --settings=foo.bar runserver
…fungerar inte längre och bör ändras till:
$ django-admin.py runserver --settings=foo.bar
Datastrukturer¶
SortedDictFromList
är borta¶
django.newforms.forms.SortedDictFromList
togs bort. django.utils.datastructures.SortedDict
kan nu instansieras med en sekvens av tupler.
För att uppdatera din kod:
Använd
django.utils.datastructures.SortedDict
där du tidigare användedjango.newforms.forms.SortedDictFromList
.Eftersom
django.utils.datastructures.SortedDict.copy
inte returnerar en deepcopy somSortedDictFromList.copy()
gjorde, måste du uppdatera din kod om du förlitade dig på en deepcopy. Gör detta genom att användacopy.deepcopy
direkt.
Funktioner för databasens backend¶
Databasens backend-funktioner har bytt namn¶
Nästan alla funktioner på databasens backend-nivå har bytt namn och/eller flyttats. Ingen av dessa har dokumenterats, men du måste ändra din kod om du använder någon av dessa funktioner, som alla finns i django.db
:
Gammal (0,96) |
Ny (1.0) |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|