0

Databasen spiller selvfølgelig en svært sentral rolle i dagens webapplikasjoner. I web-rammeverket Django håndteres dette med modeller. Dette innlegget er en introduksjon til hvordan du oppretter modeller, samt hvordan du enkelt kan gjøre endringer i modellene ved hjelp av administrasjonsgrensesnittet. I fremtidige innlegg vil jeg forklare hvordan vi kan hente ut data fra modellene våre ved hjelp av database API’et samt ORM (Object Relational Mapper).

Opprette modeller

Hvert enkelt modell representerer en tabell i databasen. Vi skal nå opprette to modeller (og dermed to tabeller) i prosjektet som vi startet i introduksjonen til Django (for de som ønsker å teste koden selv!). I motsetning til når man skrev SQL tabellene manuelt definerer man her strukturen med Python klasser. I roten til hver applikasjon i prosjektet finnes det en fil ved navn models.py. Denne filen definerer modellene for den applikasjonen. Eksempelvis på TvTid.com har jeg to applikasjoner - en for forumet og en for hele resten av prosjektet. Da kan forum-applikasjonen leve på egenhånd med sine tabeller, og kan plugges inn i andre prosjekter hvis jeg ønsker det. Dette gjør Django veldig pluggbart. Men uansett - vi skal opprette to modeller. Åpne bookmarks/main/models.py og legg inn følgende:

class Bookmark(models.Model):
	""" Denne modellen representerer et bokmerke """
	title = models.CharField(max_length=100)
	slug = models.SlugField(prepopulate_from=('title',))
	url = models.URLField()
	added = models.DateTimeField()
	clicks = models.PositiveIntegerField(default=0)
	categories = models.ManyToManyField('Category')

class Category(models.Model):
	""" Denne modellen representerer en kategori for bokmerker"""
	name = models.CharField(max_length=30)
	slug = models.SlugField(prepopulate_from=('name',))

models er tilgjengelig i scope fordi det blir importert på først linje med from django.db import models.

Hver av modellene arver fra models.Model. Som du ser er kolonnetypene ganske innlysende. Definisjonen av title i Bookmark-modellen med models.CharField(max_length=100) tilsvarer VARCHAR(100). DateTimeField() blir DATETIME, og så videre. SlugField er et felt som er VARCHAR i bakgrunnen men som brukes til å lagre “url adresse” for et objekt. Det vil altså brukes for identifisering i adresser. SlugField på en kategori kan f.eks være “data-og-internett” slik at den permanente adressen kan være noe som /kategorier/data-og-internett/. Se komplett liste over hvilke Fields som er tilgjengelig i dokumentasjonen. Her kommer et lite utdrag av de viktigste:

  • CharField - Tilsvarer VARCHAR og blir brukt for tekst inntil 255 tegn
  • DateField - Tilsvarer DATEFIELD og blir brukt for datoer
  • EmailField - Er VARCHAR i bakgrunnen men må være gyldig epost adresse
  • ImageField - arver fra FileField og er for å lagre bilde, blir VARCHAR i tabell.
  • IPAddressField - For å lagre IP-adresse
  • TextField - For å lagre tekst over 255 egn
  • URLField - For å lagre URL’er
  • ManyToManyfield - For å ha mange-til-mange relasjoner med andre modeller (les under)

ManyToManyField er for å håndtere mange-til-mange relasjoner mellom modeller. I vårt tilfelle har vi definert et field ved navn categories på Bookmark-modellen, og det betyr da at Bookmark-modellen kan ligge i mange kategorier. I bakgrunnen blir det (i neste steg) opprettet en tredje tabell som skal inneholde mange-til-mange relasjonene.

Modellene vi har definert er ikke opprettet i databasen, så da må vi bruke manage.py verktøyet til å synkronisere databasen med de definerte modellene. Som nevnt før vil syncdb ikke håndtere endringer i tabellstruktur. Hvis du legger til en kolonne må du kjøre ALTER TABLE sql manuelt for å oppdatere databasen. Hvis du bare utvikler og ikke har noe data i tabellen kan du alltids bare slette den helt og kjøre syncdb for å oppdatere. Hvis du har satt opp databasen riktig (vi gjorde det med SQLite i introduksjonen) vil du få følgende resultat av syncdb-verktøyet:

enoj@enoj-laptop:~/projects/bookmarks$ python manage.py syncdb
Creating table main_bookmark
Creating table main_category
Installing index for main.Bookmark model
Installing index for main.Category model

Som du ser ble tabellene opprettet og er klare for bruk.

Enkel redigering med det innebygde administrasjonsgrensesnittet

Med Django kommer et administrasjonsgrensesnitt rett ut av boksen. Det kan lett plugges inn og bruker samme autentisering som du selv skal bruke for å logge inn dine brukere. Det betyr at superbrukeren som ble opprettet i introduksjonen nå blir nyttig når du skal logge inn i administrasjonen. For å aktivere grensesnittet må du gjøre et par ting. Først må du legge inn django.contrib.admin under INSTALLED_APPS i settings.py. Dermed skal INSTALLED_APPS se slik ut:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'bookmarks.main',
)

Deretter må du kjøre syncdb igjen for å opprette tabellene som følger med administrasjonen (logging og lignende).

enoj@enoj-laptop:~/projects/bookmarks$ python manage.py syncdb
Creating table django_admin_log
Installing index for admin.LogEntry model

Etter man har brukt syncdb må man aktivere URL’en for administrasjonen som er definert i en fil som heter urls.py og er i roten til prosjektet. URL-struktur skal forklares i litt mer detalj i et eget innlegg, for øyeblikket kan vi bare åpne bookmarks/urls.py og fjerne kommentartegnet på linje 8, slik at innholdet blir som følger:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    # Example:
    # (r'^bookmarks/', include('bookmarks.foo.urls')),

    # Uncomment this for admin:
    (r'^admin/', include('django.contrib.admin.urls')),
)

Her benyttes en funksjon include for å inkludere en annen python fil som definerer URL-struktur. Det er da admin-applikasjonens egen URL fil som blir brukt for å definere all struktur etter /admin/.

Nå er alt som trengs til for å kunne teste administrasjonsgrensesnittet. Sørg for at utviklingsserveren kjører og åpne http://localhost:8000/admin/ i en nettleser. Utviklingsserveren startes slik:

enoj@enoj-laptop:~/projects/bookmarks$ python manage.py runserver 0:8000
Validating models...
0 errors found

Django version 0.97-pre-SVN-unknown, using settings 'bookmarks.settings'
Development server is running at http://0:8000/
Quit the server with CONTROL-C.

Hvis alt er gjort riktig skal du få opp et lignende skjermbilde i nettleseren din etter du har logget inn med superbrukeren som du opprettet tidligere:

Nå får du kun opp de modellene som kommer fra andre applikasjoner enn vår bookmarks. For å aktivere våre modeller for administrasjonen må vi opprette en indre klasse (inner class) ved navn Admin på modellen. Her kan du gi argumenter om hvilke felter som skal vises i administrasjonen, samt andre kriterier. Rediger models.py slik at modellene ser slik ut:

class Bookmark(models.Model):
	title = models.CharField(max_length=100)
	slug = models.SlugField(prepopulate_from=('title',))
	url = models.URLField()
	added = models.DateTimeField()
	clicks = models.PositiveIntegerField(default=0)
	categories = models.ManyToManyField('Category')

	class Admin:
		list_display = ('title', 'added', 'clicks',)

class Category(models.Model):
	name = models.CharField(max_length=30)
	slug = models.SlugField(prepopulate_from=('name',))

	class Admin:
		list_display = ('name',)

Hvis du nå laster administrasjonsgrensesnittet igjen (du må muligens restarte utviklingsserveren) skal du få opp modellene i vår applikasjon main som er Bookmark og Category.

Nå kan vi begynne å fylle tabellene våre med data. Det er svært praktisk å ha et slik administrasjonsgrensesnitt tilgjengelig for å redigere/oppdatere/slette/legge til alle modeller mens man utvikler. Det er betraktelig mer komfortabelt enn å jobbe med f.eks phpMyAdmin, og her kan man redigere i mange-til-en og mange-til-mange relasjoner også (som ville vært virkelig kjipt i phpMyAdmin). La oss begynne med å legge til noen kategorier. Trykk på “Legg til” i Categorys raden under main. Bruk skjemaet og legg inn 4-5 kategorier så vi har noe å jobbe med. Skjemaet for å legge til kategori er ganske selvforklarende. Etterhvert som man skriver på Name vil slug-feltet automatisk fylles ut (ved hjelp av javascript). Alle tegn som ikke passer i en URL blir da fjernet og mellomrom blir byttet ut med bindestrek (-).

Som man kan se på bildet til høyre har jeg lagt til kategoriene Sikkerhet, Fri programvare, Webrammeverk, Netthandel og Søkemotorer.

Nå som vi har noen kategorier kan vi begynne å legge inn bokmerker. Trykk på “Hjem” øverst til venstre og trykk legg til linken ved Bookmarks.

Når du får opp skjemaet for å legge til et bokmerke vil du se at i <select>-boksen hvor man skal velge kategorier står det Category object istedetfor navnet på kategorien. Dette er fordi vi ikke har definert en funksjon som returnerer tekst-representasjonen av objektet. Før skulle man da definere en funksjon __str__, men etterhvert som Django ble konvertert til å støtte Unicode ble det

For å fikse dette problemet må vi altså definere en metode __unicode__ på kategori-modellen. Som alle andre metoder i en Python klasse tar den argument self, og skal returnere det som skal være tekst-presentasjonen av objektet. I vårt tilfelle blir det da self.name. Legg inn følgende kode etter class Admin i Category-definisjonen:

	def __unicode__(self):
		return self.name

På bildet under kan du se hvordan det skal se ut når du refresher skjemaet for å legge inn bokmerke. Nå kan du begynne å legge til noen bokmerker, slik at vi har noe data å jobbe med senere.

Legg forøvrig merke til at vårt DateTimeField har blitt omgjort til to tekstfelter, et for dato og et for klokkeslett (se bildet til høyre). Det har også kommet noen javascript-snarveier man kan bruke for å hente ut nåværende dato og klokkeslett. Du kan også prøve å skrive ugyldige verdier, du vil da få opp feilmelding fra Django. Det samme gjelder ugyldige epost-adresser (EmailField), URL’er (URLField), ip-adresser (IPAddressField), og så videre.

Nå har du fått en enkel introduksjon til hvordan du kan opprette modeller i web-rammeverket Django, samt hvordan du kan aktivere modellene for administrasjon i det innebygde administrasjonsgrensesnittet. I del to forklarer jeg hvordan man kan hente informasjon fra tabellene vi har opprettet ved bruk av API og ORM (Object Relational Mapper). Stay tuned!

Her kommer et par linker fra dokumentasjon og lignende som er relevant for dette innlegget:

NB: Hvordan man bruker og aktiverer Djangos administrajonsgrensesnitt har blitt drastisk endret nå når newforms-admin har blitt merget i trunk. Dette gjør administrasjonen mer fleksibel, og man får mer kontroll over hva brukeren får tilgang til. Les mer om den nye administrasjonen i linken til dokumentasjonen som er over.

Hvis du har noen spørsmål angående Django generelt eller det jeg har skrevet i dette innlegget, så ikke nøl med å spørre ved å bruke kommentarfeltet under. Jeg skal prøve å svare så godt jeg kan.

Leave a Reply