Du modèle Python vers la base de données
Support primitif pour générer un modèle à partir d'une base existante (rétro-ingénierie pour démarrer un projet).
from django.db import models
class Adherent(models.Model):
nom = models.CharField("nom", maxlength=50)
prenom = models.CharField("prénom", maxlength=50)
naissance = models.DateField("date de naissance")
email = models.EmailField("e-mail", null=False)
adhesion = models.DateField("date d'adhésion",
auto_now=True,
editable=False)
echeance = models.DateField("date d'échéance",
null=False)
Créer le modèle en base :
./manage.py syncdb
Code DDL exécuté pour SQLite3 :
BEGIN;
CREATE TABLE "adherent" (
"id" integer NOT NULL PRIMARY KEY,
"nom" varchar(50) NOT NULL,
"prenom" varchar(50) NOT NULL,
"naissance" date NOT NULL,
"email" varchar(75) NOT NULL,
"adhesion" date NOT NULL,
"echeance" date NOT NULL
);
COMMIT;
./manage.py runserver
Manipuler les données, avec la console Python :
$ ./manage.py shell >>> from si.models import Adherent >>> Adherent.objects.all() [] >>> from datetime import date >>> om = Adherent(nom='Mengué', prenom='Olivier', ... naissance=date(1974, 1, 1), ... adhesion=date(2000, 9, 5), ... echeance=date(2007, 9, 4)) >>> om.save() >>> Adherent.objects.all() [<Adherent: Mengué, Olivier>]
from django.db import models from datetime import date
class Adherent(models.Model):
nom = models.CharField("nom", maxlength=50)
prenom = models.CharField("prénom", maxlength=50)
# ...
def __str__(self):
return '%s, %s' % (self.nom, self.prenom)
class Meta:
db_table = 'adherent'
verbose_name = 'Adhérent'
verbose_name_plural = 'Adhérents'
def cotisation_a_jour(self):
return self.echeance > date.today()
L'API de requêtage utilise la reflexivité de Python
>>> Adherent.objects.all()
[<Adherent: Mengué, Olivier>, <Adherent: Lafarine, Francine>]
>>> Adherent.objects.order_by('nom')
[<Adherent: Lafarine, Francine>, <Adherent: Mengué, Olivier> ]
>>> Adherent.objects.filter(nom='Mengué')
[<Adherent: Mengué, Olivier>]
>>> Adherent.objects.filter(nom__contains='ine')
[<Adherent: Lafarine, Francine>]
Équivalent Perl :
Adherent->objects->filter('nom__contains' => 'ine');
qs = Adherent.object.all()
.filter(naissance__gte=date(1966, 1, 1))
.filter(echeance__gte=date.today())
SQL :
SELECT * FROM adherent WHERE naissance >= '1966-01-01'
AND echeance >= NOW
L'évaluation paresseuse permet des filtres conditionnels:
if affichage == 'N':
qs = qs.order_by('naissance')
class Animateur(models.Model):
adherent = models.OneToOneField(Adherent,
verbose_name='adhérent')
date_diplome = models.DateField('date du diplôme',
auto_now_add=True, null=False, editable=True)
parrain = models.ForeignKey('self', null=True)
class Rando(models.Model):
CHOIX_RYTHMES = (
('L', 'Lent'),
('M', 'Moyen'),
('S', 'Soutenu'),
('R', 'Rapide'),
)
jour = models.DateField()
titre = models.CharField("titre", maxlength=250,
unique_for_date="jour")
distance = models.IntegerField("distance (km)")
rythme = models.CharField("rythme", maxlength=1,
choices=CHOIX_RYTHMES)
publication = models.DateField()
descriptif = models.TextField()
animateurs = models.ManyToManyField(Animateur,
related_name='randos')
premier = Adherent.object.all()[0]
cinq_a_dix = Adherent.object.all()[5:10]
for a in Adherent.object.all(): print a
Animateur.parrain = None
minimiser les accès
optimisation des requêtes
appels explicites : save(), select_related()
Animateur.object.get(adherent__nom='Kelner').randos.all()
pas d'objets externes à importer, mais des méthodes simples directement appliquées aux objets
jointures transparentes si besoin
tous les objets accèdent à tous les autres