# Django 6.0.7 documentation

# Skriva din första Django-app, del 2

Denna tutorial börjar där Tutorial 1 slutade. Vi ställer in databasen, skapar din första modell och får en snabb introduktion till Djangos automatiskt genererade administratörssida.

Var du kan få hjälp:

Om du har problem med att gå igenom den här handledningen kan du gå till avsnittet Att få hjälp i FAQ.

## Uppsättning av databas

Öppna nu `mysite/settings.py`. Det är en vanlig Python-modul med variabler på modulnivå som representerar Django-inställningar.

Som standard använder konfigurationen `DATABASER` SQLite. Om du är nybörjare på databaser, eller bara är intresserad av att prova Django, är detta det enklaste valet. SQLite ingår i Python, så du behöver inte installera något annat för att stödja din databas. När du startar ditt första riktiga projekt kanske du dock vill använda en mer skalbar databas som PostgreSQL för att undvika huvudvärk för databasbyte längs vägen.

Om du vill använda en annan databas, se detaljer för att anpassa och få igång din databas.

Medan du redigerar `mysite/settings.py`, ställ in `TIME_ZONE` till din tidszon.

Lägg också märke till `INSTALLED_APPS` högst upp i filen. Den innehåller namnen på alla Django-applikationer som är aktiverade i den här Django-instansen. Appar kan användas i flera projekt, och du kan paketera och distribuera dem för användning av andra i deras projekt.

Som standard innehåller `INSTALLED_APPS` följande appar, som alla levereras med Django:

- `django.contrib.admin` – Administrationssidan. Du kommer att använda den inom kort.

- `django.contrib.auth` – Ett system för autentisering.

- `django.contrib.contenttypes` – Ett ramverk för innehållstyper.

- `django.contrib.sessions` – Ett ramverk för sessioner.

- `django.contrib.messages` – Ett ramverk för meddelanden.

- `django.contrib.staticfiles` – Ett ramverk för hantering av statiska filer.

Dessa applikationer ingår som standard som en bekvämlighet för det vanliga fallet.

Vissa av dessa program använder dock minst en databastabell, så vi måste skapa tabellerna i databasen innan vi kan använda dem. Det gör du genom att köra följande kommando:

/ 

    $ python manage.py migrate

    ...\> py manage.py migrate

Kommandot `migrate` tittar på inställningen `INSTALLED_APPS` och skapar alla nödvändiga databastabeller enligt databasinställningarna i filen `mysite/settings.py` och de databasmigreringar som levereras med appen (vi går igenom dem senare). Du kommer att se ett meddelande för varje migrering som den tillämpar. Om du är intresserad kan du köra kommandoradsklienten för din databas och skriva `dt` (PostgreSQL), `SHOW TABLES;` (MariaDB, MySQL), `.tables` (SQLite) eller `SELECT TABLE_NAME FROM USER_TABLES;` (Oracle) för att visa de tabeller som Django skapade.

För minimalisterna

Som vi sa ovan ingår standardapplikationerna för det vanliga fallet, men alla behöver dem inte. Om du inte behöver någon eller alla av dem kan du kommentera ut eller ta bort lämpliga rader från `INSTALLED_APPS` innan du kör `migrate`. Kommandot `migrate` kommer endast att köra migreringar för appar i `INSTALLED_APPS`.

## Skapa modeller

Nu ska vi definiera dina modeller - i princip din databaslayout, med ytterligare metadata.

Filosofi

En modell är den enda, definitiva källan till information om dina data. Den innehåller de viktigaste fälten och beteendena för de data du lagrar. Django följer DRY-principen. Målet är att definiera din datamodell på ett ställe och automatiskt härleda saker från den.

This includes the migrations, which are derived from your models file. They form a history that Django uses to update your database schema to match your current models.

I vår poll-app skapar vi två modeller: `Question` och `Choice`. En `Question` har en fråga och ett publiceringsdatum. En `Choice` har två fält: texten i valet och en rösträkning. Varje `Choice` är associerat med en `Question`.

Dessa koncept representeras av Python-klasser. Redigera filen `polls/models.py` så att den ser ut så här:

`polls/modeller.py`

    from django.db import models

    class Question(models.Model):
        question_text = models.CharField(max_length=200)
        pub_date = models.DateTimeField("date published")

    class Choice(models.Model):
        question = models.ForeignKey(Question, on_delete=models.CASCADE)
        choice_text = models.CharField(max_length=200)
        votes = models.IntegerField(default=0)

Här representeras varje modell av en klass som subklassar `django.db.models.Model`. Varje modell har ett antal klassvariabler, som var och en representerar ett databasfält i modellen.

Varje fält representeras av en instans av en `Field`-klass - t.ex. `CharField` för teckenfält och `DateTimeField` för datatider. Detta talar om för Django vilken typ av data varje fält innehåller.

Namnet på varje `Field`-instans (t.ex. `question_text` eller `pub_date`) är fältets namn i ett maskinvänligt format. Du kommer att använda detta värde i din Python-kod och din databas kommer att använda det som kolumnnamn.

Du kan använda ett valfritt första positionellt argument till en `Field` för att ange ett mänskligt läsbart namn. Det används i ett par introspektiva delar av Django, och det fungerar även som dokumentation. Om detta fält inte tillhandahålls kommer Django att använda det maskinläsbara namnet. I det här exemplet har vi bara definierat ett mänskligt läsbart namn för `Question.pub_date`. För alla andra fält i denna modell kommer fältets maskinläsbara namn att räcka som dess mänskligt läsbara namn.

Vissa `Field`-klasser har obligatoriska argument. `CharField`, till exempel, kräver att du ger den en `max_length`. Det används inte bara i databasschemat utan även i valideringen, som vi snart ska se.

En `Field` kan också ha olika valfria argument; i det här fallet har vi satt `default`-värdet för `votes` till 0.

Slutligen, notera att ett förhållande definieras med `ForeignKey`. Det säger till Django att varje `Choice` är relaterad till en enda `Question`. Django stöder alla vanliga databasrelationer: många-till-en, många-till-många och en-till-en.

## Aktivering av modeller

Den lilla biten modellkod ger Django en hel del information. Med den kan Django göra följande:

- Skapa ett databasschema (`CREATE TABLE`-uttalanden) för den här appen.

- Skapa ett Python API för databasåtkomst för åtkomst till objekten `Question` och `Choice`.

Men först måste vi tala om för vårt projekt att appen `polls` är installerad.

Filosofi

Django-appar är ”pluggbara”: Du kan använda en app i flera projekt och du kan distribuera appar, eftersom de inte behöver vara knutna till en viss Django-installation.

För att inkludera appen i vårt projekt måste vi lägga till en referens till dess konfigurationsklass i inställningen `INSTALLED_APPS`. Klassen `PollsConfig` finns i filen `polls/apps.py`, så dess prickade sökväg är `'polls.apps.PollsConfig'`. Redigera filen `mysite/settings.py` och lägg till den prickade sökvägen i inställningen `INSTALLED_APPS`. Det kommer att se ut så här:

`mysite/settings.py`

    INSTALLED_APPS = [
        "polls.apps.PollsConfig",
        "django.contrib.admin",
        "django.contrib.auth",
        "django.contrib.contenttypes",
        "django.contrib.sessions",
        "django.contrib.messages",
        "django.contrib.staticfiles",
    ]

Nu vet Django att appen `polls` ska inkluderas. Låt oss köra ett annat kommando:

/ 

    $ python manage.py makemigrations polls

    ...\> py manage.py makemigrations polls

Du bör se något som liknar följande:

    Migrations for 'polls':
      polls/migrations/0001_initial.py
        + Create model Question
        + Create model Choice

Genom att köra `makemigrations` talar du om för Django att du har gjort några ändringar i dina modeller (i det här fallet har du gjort nya) och att du vill att ändringarna ska lagras som en migration.

Migreringar är hur Django lagrar ändringar i dina modeller (och därmed ditt databasschema) - de är filer på disken. Du kan läsa migreringen för din nya modell om du vill; det är filen `polls/migrations/0001_initial.py`. Oroa dig inte, du förväntas inte läsa dem varje gång Django gör en, men de är utformade för att vara mänskligt redigerbara om du manuellt vill justera hur Django ändrar saker.

Det finns ett kommando som kör migreringarna åt dig och hanterar ditt databasschema automatiskt - det kallas `migrate`, och vi kommer till det om en stund - men först ska vi se vilken SQL den migreringen skulle köra. Kommandot `sqlmigrate` tar migreringsnamn och returnerar deras SQL:

/ 

    $ python manage.py sqlmigrate polls 0001

    ...\> py manage.py sqlmigrate polls 0001

Du bör se något som liknar följande (vi har omformat det för läsbarhetens skull):

    BEGIN;
    --
    -- Create model Question
    --
    CREATE TABLE "polls_question" (
        "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
        "question_text" varchar(200) NOT NULL,
        "pub_date" timestamp with time zone NOT NULL
    );
    --
    -- Create model Choice
    --
    CREATE TABLE "polls_choice" (
        "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
        "choice_text" varchar(200) NOT NULL,
        "votes" integer NOT NULL,
        "question_id" bigint NOT NULL
    );
    ALTER TABLE "polls_choice"
      ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
        FOREIGN KEY ("question_id")
        REFERENCES "polls_question" ("id")
        DEFERRABLE INITIALLY DEFERRED;
    CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");

    COMMIT;

Notera följande:

- Den exakta utmatningen varierar beroende på vilken databas du använder. Exemplet ovan genereras för PostgreSQL.

- Tabellnamnen genereras automatiskt genom att kombinera appens namn (`polls`) och modellens namn med gemener – `question` och `choice`. (Du kan åsidosätta detta beteende.)

- Primärnycklar (ID:n) läggs till automatiskt. (Du kan även åsidosätta detta.)

- Enligt konvention lägger Django till `"_id"` till fältnamnet för den främmande nyckeln. (Ja, du kan åsidosätta detta också)

- Det främmande nyckelförhållandet görs explicit av en `` FOREIGN KEY `` begränsning. Oroa dig inte för `` DEFERRABLE`` -delarna; det säger till PostgreSQL att inte genomdriva den främmande nyckeln förrän i slutet av transaktionen.

- Den är skräddarsydd för den databas du använder, så databasspecifika fälttyper som `auto_increment` (MySQL), `bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY` (PostgreSQL) eller `integer primary key autoincrement` (SQLite) hanteras automatiskt åt dig. Detsamma gäller för citering av fältnamn - t.ex. med dubbla citat eller enkla citat.

- Kommandot `sqlmigrate` kör faktiskt inte migreringen på din databas - istället skriver det ut den på skärmen så att du kan se vilken SQL Django tror krävs. Det är användbart för att kontrollera vad Django kommer att göra eller om du har databasadministratörer som kräver SQL-skript för ändringar.

Om du är intresserad kan du också köra `python manage.py check`; detta kontrollerar eventuella problem i ditt projekt utan att göra migreringar eller röra databasen.

Kör nu `migrate` igen för att skapa dessa modelltabeller i din databas:

/ 

    $ python manage.py migrate
    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, polls, sessions
    Running migrations:
      Applying polls.0001_initial... OK

    ...\> py manage.py migrate
    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, polls, sessions
    Running migrations:
      Applying polls.0001_initial... OK

Kommandot `migrate` tar alla migreringar som inte har tillämpats (Django spårar vilka som tillämpas med hjälp av en speciell tabell i din databas som heter `django_migrations`) och kör dem mot din databas - i huvudsak synkroniserar de ändringar du gjorde i dina modeller med schemat i databasen.

Migreringar är mycket kraftfulla och låter dig ändra dina modeller över tid, när du utvecklar ditt projekt, utan att du behöver ta bort din databas eller tabeller och skapa nya - det är specialiserat på att uppgradera din databas live, utan att förlora data. Vi kommer att gå igenom dem mer ingående i en senare del av handledningen, men för tillfället bör du komma ihåg trestegsguiden för att göra modelländringar:

- Ändra dina modeller (i `models.py`).

- Run `python manage.py makemigrations` to create migrations for those changes.

- Kör `python manage.py migrate` för att tillämpa dessa ändringar i databasen.

Anledningen till att det finns separata kommandon för att skapa och tillämpa migreringar är att du ska överföra migreringar till ditt versionshanteringssystem och skicka dem med din app; de gör inte bara din utveckling enklare, de kan också användas av andra utvecklare och i produktionen.

Läs django-admin-dokumentationen för fullständig information om vad verktyget `manage.py` kan göra.

## Leka med API:et

Låt oss nu hoppa in i det interaktiva Python-skalet och leka med det kostnadsfria API som Django ger dig. För att anropa Python-skalet använder du det här kommandot:

/ 

    $ python manage.py shell

    ...\> py manage.py shell

Vi använder detta i stället för att helt enkelt skriva ”python”, eftersom `manage.py` ställer in miljövariabeln `DJANGO_SETTINGS_MODULE`, som ger Django Python-importsökvägen till din `mysite/settings.py`-fil. Som standard importerar kommandot `shell` automatiskt modellerna från din `INSTALLED_APPS`.

När du väl är inne i skalet kan du utforska databas-API:

    # No questions are in the system yet.
    >>> Question.objects.all()
    <QuerySet []>

    # Create a new Question.
    # Support for time zones is enabled in the default settings file, so
    # Django expects a datetime with tzinfo for pub_date. Use timezone.now()
    # instead of datetime.datetime.now() and it will do the right thing.
    >>> from django.utils import timezone
    >>> q = Question(question_text="What's new?", pub_date=timezone.now())

    # Save the object into the database. You have to call save() explicitly.
    >>> q.save()

    # Now it has an ID.
    >>> q.id
    1

    # Access model field values via Python attributes.
    >>> q.question_text
    "What's new?"
    >>> q.pub_date
    datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=datetime.UTC)

    # Change values by changing the attributes, then calling save().
    >>> q.question_text = "What's up?"
    >>> q.save()

    # objects.all() displays all the questions in the database.
    >>> Question.objects.all()
    <QuerySet [<Question: Question object (1)>]>

Vänta lite. `<Fråga: Fråga objekt (1)>` är inte en användbar representation av detta objekt. Låt oss fixa det genom att redigera modellen `Question` (i filen `polls/models.py`) och lägga till en `__str__()`-metod till både `Question` och `Choice`:

`polls/modeller.py`

    from django.db import models

    class Question(models.Model):
        # ...
        def __str__(self):
            return self.question_text

    class Choice(models.Model):
        # ...
        def __str__(self):
            return self.choice_text

Det är viktigt att lägga till `__str__()`-metoder till dina modeller, inte bara för din egen bekvämlighet när du hanterar den interaktiva prompten, utan också för att objektens representationer används i Djangos automatiskt genererade admin.

Låt oss också lägga till en anpassad metod till den här modellen:

`polls/modeller.py`

    import datetime

    from django.db import models
    from django.utils import timezone

    class Question(models.Model):
        # ...
        def was_published_recently(self):
            return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

Notera tillägget av `import datetime` och `from django.utils import timezone`, för att referera till Pythons standardmodul `datetime` respektive Djangos tidszonsrelaterade verktyg i `django.utils.timezone`. Om du inte är bekant med tidszonshantering i Python kan du lära dig mer i time zone support docs.

Spara dessa ändringar och starta ett nytt interaktivt Python-skal. (Om en prompt med tre vinklar (>>>) indikerar att du fortfarande befinner dig i skalet måste du först avsluta med `exit()`). Kör `python manage.py shell` igen för att uppdatera modellerna.

    # Make sure our __str__() addition worked.
    >>> Question.objects.all()
    <QuerySet [<Question: What's up?>]>

    # Django provides a rich database lookup API that's entirely driven by
    # keyword arguments.
    >>> Question.objects.filter(id=1)
    <QuerySet [<Question: What's up?>]>
    >>> Question.objects.filter(question_text__startswith="What")
    <QuerySet [<Question: What's up?>]>

    # Get the question that was published this year.
    >>> from django.utils import timezone
    >>> current_year = timezone.now().year
    >>> Question.objects.get(pub_date__year=current_year)
    <Question: What's up?>

    # Request an ID that doesn't exist, this will raise an exception.
    >>> Question.objects.get(id=2)
    Traceback (most recent call last):
        ...
    DoesNotExist: Question matching query does not exist.

    # Lookup by a primary key is the most common case, so Django provides a
    # shortcut for primary-key exact lookups.
    # The following is identical to Question.objects.get(id=1).
    >>> Question.objects.get(pk=1)
    <Question: What's up?>

    # Make sure our custom method worked.
    >>> q = Question.objects.get(pk=1)
    >>> q.was_published_recently()
    True

    # Give the Question a couple of Choices. The create call constructs a new
    # Choice object, does the INSERT statement, adds the choice to the set
    # of available choices and returns the new Choice object. Django creates
    # a set (defined as "choice_set") to hold the "other side" of a ForeignKey
    # relation (e.g. a question's choice) which can be accessed via the API.
    >>> q = Question.objects.get(pk=1)

    # Display any choices from the related object set -- none so far.
    >>> q.choice_set.all()
    <QuerySet []>

    # Create three choices.
    >>> q.choice_set.create(choice_text="Not much", votes=0)
    <Choice: Not much>
    >>> q.choice_set.create(choice_text="The sky", votes=0)
    <Choice: The sky>
    >>> c = q.choice_set.create(choice_text="Just hacking again", votes=0)

    # Choice objects have API access to their related Question objects.
    >>> c.question
    <Question: What's up?>

    # And vice versa: Question objects get access to Choice objects.
    >>> q.choice_set.all()
    <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
    >>> q.choice_set.count()
    3

    # The API automatically follows relationships as far as you need.
    # Use double underscores to separate relationships.
    # This works as many levels deep as you want; there's no limit.
    # Find all Choices for any question whose pub_date is in this year
    # (reusing the 'current_year' variable we created above).
    >>> Choice.objects.filter(question__pub_date__year=current_year)
    <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

    # Let's delete one of the choices. Use delete() for that.
    >>> c = q.choice_set.filter(choice_text__startswith="Just hacking")
    >>> c.delete()

För mer information om modellrelationer, se Accessing related objects. Mer information om hur du använder dubbla understrykningstecken för att göra fältuppslagningar via API:et finns i Field lookups. För fullständig information om databas-API:et, se vår Database API reference.

## Introduktion till Django Admin

Filosofi

Att skapa administratörswebbplatser för din personal eller dina kunder för att lägga till, ändra och ta bort innehåll är ett tråkigt arbete som inte kräver mycket kreativitet. Av den anledningen automatiserar Django helt skapandet av administratörsgränssnitt för modeller.

Django skrevs i en nyhetsrumsmiljö, med en mycket tydlig åtskillnad mellan ”innehållsutgivare” och den ”offentliga” webbplatsen. Webbplatsadministratörer använder systemet för att lägga till nyheter, händelser, sportresultat etc., och det innehållet visas på den offentliga webbplatsen. Django löser problemet med att skapa ett enhetligt gränssnitt för webbplatsadministratörer för att redigera innehåll.

Administratören är inte avsedd att användas av webbplatsbesökare. Den är till för webbplatsansvariga.

### Skapa en administratörsanvändare

Först måste vi skapa en användare som kan logga in på administratörssidan. Kör följande kommando:

/ 

    $ python manage.py createsuperuser

    ...\> py manage.py createsuperuser

Ange önskat användarnamn och tryck på Enter.

    Username: admin

Du kommer sedan att bli ombedd att ange önskad e-postadress:

    Email address: admin@example.com

Det sista steget är att ange ditt lösenord. Du kommer att bli ombedd att ange ditt lösenord två gånger, den andra gången som en bekräftelse på den första.

    Password: **********
    Password (again): *********
    Superuser created successfully.

### Starta utvecklingsservern

Django-administratörssidan är aktiverad som standard. Låt oss starta utvecklingsservern och utforska den.

Om servern inte är igång startar du den på följande sätt:

/ 

    $ python manage.py runserver

    ...\> py manage.py runserver

Öppna nu en webbläsare och gå till ”/admin/” på din lokala domän, t.ex. http://127.0.0.1:8000/admin/. Du bör se administratörens inloggningsskärm:

Eftersom translation är aktiverad som standard, om du anger `LANGUAGE_CODE`, kommer inloggningsskärmen att visas på det angivna språket (om Django har lämpliga översättningar).

### Ange administratörens webbplats

Försök nu att logga in med det superanvändarkonto som du skapade i föregående steg. Du bör se Django-administratörens indexsida:

Du bör se några typer av redigerbart innehåll: grupper och användare. De tillhandahålls av `django.contrib.auth`, det autentiseringsramverk som levereras av Django.

### Gör röstningsappen ändringsbar i administratören

Men var är vår poll-app? Den visas inte på adminindexsidan.

Det är bara en sak kvar att göra: vi måste tala om för administratören att `Question`-objekt har ett administratörsgränssnitt. För att göra detta, öppna filen `polls/admin.py` och redigera den så att den ser ut så här:

`polls/admin.py`

    from django.contrib import admin

    from .models import Question

    admin.site.register(Question)

### Utforska de kostnadsfria adminfunktionerna

Nu när vi har registrerat `Question` vet Django att den ska visas på adminindexsidan:

Klicka på ”Frågor”. Nu är du på sidan ”Ändra lista” för frågor. På den här sidan visas alla frågor i databasen och du kan välja en fråga för att ändra den. Det finns frågan ”Vad händer?” som vi skapade tidigare:

Klicka på frågan ”Vad händer?” för att redigera den:

Saker att notera här:

- Formuläret genereras automatiskt från modellen `Question`.

- De olika modellfälttyperna (`DateTimeField`, `CharField`) motsvarar lämplig HTML-inmatningswidget. Varje fälttyp vet hur den ska visas i Django-admin.

- Varje `DateTimeField` får gratis JavaScript-genvägar. Datum får en ”Today”-genväg och en popup-kalender, och tider får en ”Now”-genväg och en praktisk popup som listar vanliga inmatade tider.

Längst ner på sidan finns ett par alternativ:

- Save – Sparar ändringar och återgår till sidan med ändringslistan för den här typen av objekt.

- Spara och fortsätt redigera – Sparar ändringar och laddar om adminsidan för det här objektet.

- Save and add another – Sparar ändringar och laddar ett nytt, tomt formulär för den här typen av objekt.

- Delete – Visar en bekräftelsesida för radering.

Om värdet för ”Date published” inte stämmer överens med den tidpunkt då du skapade frågan i Tutorial 1, betyder det förmodligen att du har glömt att ange rätt värde för inställningen `TIME_ZONE`. Ändra den, ladda om sidan och kontrollera att rätt värde visas.

Ändra ”Datum publicerat” genom att klicka på genvägarna ”Idag” och ”Nu”. Klicka sedan på ”Spara och fortsätt redigera” Klicka sedan på ”Historik” längst upp till höger. Du kommer att se en sida som listar alla ändringar som gjorts i detta objekt via Django-admin, med tidsstämpel och användarnamn för den person som gjorde ändringen:

När du känner dig bekväm med API:et för modeller och har bekantat dig med adminwebbplatsen kan du läsa del 3 av denna handledning för att lära dig hur du lägger till fler vyer i vår polls-app.