# Django 5.2.8 documentation

# 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 versionsinformation. 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)
--- | ---
`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: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)
--- | ---
`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 `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 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)`

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

### Malltaggar

#### `utrymmeslös` tagg

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

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

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.

### 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

### Syndikering

#### `Feed.__init__` har ändrats

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.

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

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