Porta dina appar från Django 0.96 till 1.0Link to this heading

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.

Vanliga förändringarLink to this heading

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 UnicodeLink to this heading

Ä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.

ModellerLink to this heading

Vanliga ändringar i din models-fil:

Byt namn på maxlength till max_lengthLink to this heading

Byt namn på argumentet maxlength till max_length (detta ändrades för att vara konsekvent med formulärfält):

Ersätt __str__ med __unicode__Link to this heading

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_fromLink to this heading

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ärnaLink to this heading

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.pyLink to this heading

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.

ExempelLink to this heading

Nedan följer ett exempel på filen models.py med alla de ändringar du behöver göra:

Gammal (0.96) models.py:

Code
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:

Code
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:

Code
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örenLink to this heading

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-syntaxLink to this heading

De nya edit_inline-alternativen har alla flyttats till admin.py. Här är ett exempel:

Gammal (0,96):

Code
class Parent(models.Model): ...


class Child(models.Model):
    parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)

Ny (1.0):

Code
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 fieldsetsLink to this heading

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):

Code
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):

Code
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"}),
    )

URL:erLink to this heading

Uppdatera din root urls.pyLink to this heading

Om du använder administratörssidan måste du uppdatera din root urls.py.

Gammal (0.96) urls.py:

Code
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:

Code
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 ...
)

VyerLink to this heading

Använd django.forms istället för newformsLink to this heading

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:

Code
from django import newforms as forms

Ny:

Code
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:etLink to this heading

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:

Code
def my_view(request):
    f = request.FILES["file_field_name"]
    ...

…måste du göra följande ändringar:

Gammal (0,96)

Ny (1.0)

f['content']

f.read()

f['filnamn']

f.namn

f['content-type']

f.content_type

Arbeta med filfält med hjälp av det nya API:etLink to this heading

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)

myfile.get_content_filename()

minfil.innehåll.sökväg

myfile.get_content_url()

minfil.innehåll.url

myfile.get_content_size()

minfil.innehåll.storlek

myfile.save_content_file()

myfile.content.save()

myfile.get_content_width()

myfile.content.width

myfile.get_content_height()

myfile.content.height

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 ObjectPaginatorLink to this heading

ObjectPaginator i 0.96 har tagits bort och ersatts med en förbättrad version, django.core.paginator.Paginator.

MallarLink to this heading

Lär dig att älska autoescapingLink to this heading

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:

Django template
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:

Django template
{% autoescape off %}
   ... unescaped template content here ...
{% endautoescape %}

Mindre vanliga förändringarLink to this heading

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.

SignalerLink to this heading

  • 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 i django.dispatch.dispatcher.

  • Ta bort all användning av avsändaralternativen Anonymous och Any; de finns inte längre. Du kan fortfarande ta emot signaler som skickas av vilken avsändare som helst genom att använda sender=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)

def callback(avsändare)

def callback(avsändare, **kwargs)

sig = objekt()

sig = django.dispatch.Signal()

dispatcher.connect(callback, sig)

sig.connect(callback)

dispatcher.send(sig, avsändare)

sig.send(avsändare)

dispatcher.connect(callback, sig, avsändare=Any)

sig.connect(callback, avsändare=None)

KommentarerLink to this heading

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.

MalltaggarLink to this heading

utrymmeslös taggLink to this heading

Malltaggen spaceless tar nu bort alla mellanslag mellan HTML-taggar, istället för att bevara ett enda mellanslag.

Lokala smakerLink to this heading

Lokal smak från USALink to this heading

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.

SessionerLink to this heading

Få en ny sessionsnyckelLink to this heading

SessionBase.get_new_session_key() har bytt namn till _get_new_session_key(). get_new_session_object() finns inte längre.

FixturerLink to this heading

Laddning av en rad kräver inte längre save()Link to this heading

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ällningarLink to this heading

Bättre undantagLink to this heading

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 flyttatsLink to this heading

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 uppdateratsLink to this heading

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:

Code
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:

Code
r"/some_prefix/(.*/)$"

Mindre modellförändringarLink to this heading

Olika undantag från get()Link to this heading

Hanterare returnerar nu ett MultipleObjectsReturned undantag istället för AssertionError:

Gammal (0,96):

Code
try:
    Model.objects.get(...)
except AssertionError:
    handle_the_error()

Ny (1.0):

Code
try:
    Model.objects.get(...)
except Model.MultipleObjectsReturned:
    handle_the_error()

LazyDate har avfyratsLink to this heading

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):

Code
class Article(models.Model):
    title = models.CharField(maxlength=100)
    published = models.DateField(default=LazyDate())

Ny (1.0):

Code
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 floatLink to this heading

Gammal (0,96):

Code
class MyModel(models.Model):
    field_name = models.FloatField(max_digits=10, decimal_places=3)
    ...

Ny (1.0):

Code
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.

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:

Shell
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml

Anteckningar:

  1. 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.

  2. 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.

  3. 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.

InternationaliseringLink to this heading

django.views.i18n.set_language() kräver nu en POST-begäranLink to this heading

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 programLink to this heading

_() (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:

Code
from django.utils.translation import ugettext as _

Objekt för HTTP-begäran/-svarLink to this heading

Dictionary-åtkomst till HttpRequestLink to this heading

HttpRequest objects no longer directly support dictionary-style access; previously, both GET and POST data were directly available on the HttpRequest object (e.g., you could check for a piece of form data by using if 'some_form_key' in request or by reading request['some_form_key']). This is no longer supported; if you need access to the combined GET and POST data, use request.REQUEST instead.

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-rubrikerLink to this heading

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 relationerLink to this heading

Generiska relationer har flyttats ut ur kärnanLink to this heading

De generiska relationsklasserna - GenericForeignKey och GenericRelation - har flyttats till modulen django.contrib.contenttypes.

TestarLink to this heading

django.test.Client.login() har ändratsLink to this heading

Gammal (0,96):

Code
from django.test import Client

c = Client()
c.login("/path/to/login", "myuser", "mypassword")

Ny (1.0):

Code
# ... same as above, but then:
c.login(username="myuser", password="mypassword")

LedningskommandonLink to this heading

Kör kommandon för hantering från din kodLink to this heading

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:

Code
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:

Code
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å alternativLink to this heading

django-admin.py och manage.py kräver nu att underkommandon föregår alternativen. Så här är det:

Shell
$ django-admin.py --settings=foo.bar runserver

…fungerar inte längre och bör ändras till:

Shell
$ django-admin.py runserver --settings=foo.bar

SyndikeringLink to this heading

Feed.__init__ har ändratsLink to this heading

Metoden __init__() i syndikeringsramverkets klass Feed tar nu ett HttpRequest-objekt som sin andra parameter, istället för feedens URL. Detta gör att syndikeringsramverket kan fungera utan att kräva webbplatsramverket. Detta påverkar endast kod som subklassar Feed och åsidosätter metoden __init__(), och kod som anropar Feed.__init__() direkt.

DatastrukturerLink to this heading

SortedDictFromList är bortaLink to this heading

django.newforms.forms.SortedDictFromList togs bort. django.utils.datastructures.SortedDict kan nu instansieras med en sekvens av tupler.

För att uppdatera din kod:

  1. Använd django.utils.datastructures.SortedDict där du tidigare använde django.newforms.forms.SortedDictFromList.

  2. Eftersom django.utils.datastructures.SortedDict.copy inte returnerar en deepcopy som SortedDictFromList.copy() gjorde, måste du uppdatera din kod om du förlitade dig på en deepcopy. Gör detta genom att använda copy.deepcopy direkt.

Funktioner för databasens backendLink to this heading

Databasens backend-funktioner har bytt namnLink to this heading

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)

backend.get_autoinc_sql

anslutning.ops.autoinc_sql

backend.get_date_extract_sql

anslutning.ops.datum_extrahera_sql

backend.get_date_trunc_sql

anslutning.ops.datum_trunc_sql

backend.get_datetime_cast_sql

anslutning.ops.datetime_cast_sql

backend.get_deferrable_sql

anslutning.ops.deferrable_sql

backend.get_drop_foreignkey_sql

anslutning.ops.drop_foreignkey_sql

backend.get_fulltext_search_sql

anslutning.ops.fulltext_search_sql

backend.get_last_insert_id

anslutning.ops.sista_insättning_id

backend.get_limit_offset_sql

anslutning.ops.limit_offset_sql

backend.get_max_name_length

anslutning.ops.max_namn_längd

backend.get_pk_default_value

connection.ops.pk_default_value

backend.get_random_function_sql

anslutning.ops.random_function_sql

backend.get_sql_flush

anslutning.ops.sql_flush

backend.get_sql_sequence_reset

anslutning.ops.sequence_reset_sql

backend.get_start_transaction_sql

anslutning.ops.start_transaktion_sql

backend.get_tablespace_sql

anslutning.ops.tablespace_sql

backend.quote_name

anslutning.ops.quote_namn

backend.get_query_set_class

connection.ops.query_set_class

backend.get_field_cast_sql

anslutning.ops.fält_cast_sql

backend.get_drop_sequence

anslutning.ops.drop_sequence_sql

backend.OPERATOR_MAPPING

anslutning.operatörer

backend.tillåter_gruppering_per_ordinal

anslutning.funktioner.tillåter_gruppering_vid_ordinal

backend.allows_unique_and_pk

anslutning.funktioner.tillåter_unika_och_pk

backend.autoindexes_primära_nycklar

anslutning.funktioner.autoindex_primära_nycklar

backend.needs_datetime_string_cast

anslutning.funktioner.behöver_datatid_sträng_cast

backend.needs_upper_for_iops

anslutning.funktioner.behov_av_övre_del_för_iops

backend.stöd_begränsningar

anslutning.funktioner.stödjer_begränsningar

backend.stöder_bordsytor

anslutning.funktioner.stödjer_bordsytor

backend.uses_case_insensitive_names

connection.features.uses_case_insensitive_names

backend.uses_custom_queryset backend.uses_custom_queryset

anslutning.funktioner.använder_custom_queryset