minimal/django-orm

Environnement virtuel Python3, installation de Django

$ python3 -m venv venv
$ source venv/bin/activate
$ pip install django

Création d’un projet Django django_orm

$ django-admin startproject django_orm
$ cd django_orm

Création d’une ‘application’ foods dans le projet django_orm

$ python manage.py startapp foods
$ cat django_orm/settings.py
...

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'foods', # <<< ajouter
]
...

Édition des modèles de données

$ cat foods/models.py
from django.db import models


class Nutrient(models.Model):
    name = models.CharField('nom', max_length=100)

    def __str__(self):
        return self.name

class Grp(models.Model):
    code = models.CharField(primary_key=True, default='', max_length=100)
    name = models.CharField('nom', max_length=100)
    father_grp = models.ForeignKey('Grp', null=True, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class Food(models.Model):
    code = models.CharField(primary_key=True, default='', max_length=100)
    name = models.CharField('nom', max_length=100)
    grp = models.ForeignKey(Grp, null=True, on_delete=models.CASCADE)
    ssgrp = models.ForeignKey(Grp, null=True, on_delete=models.CASCADE, related_name='ssgrp')
    ssssgrp = models.ForeignKey(Grp, null=True, on_delete=models.CASCADE, related_name='ssssgrp')

    def __str__(self):
        return "{}, {}".format(self.name, self.grp)

class NutData(models.Model):
    food = models.ForeignKey(Food, on_delete=models.CASCADE)
    nutrient = models.ForeignKey(Nutrient, on_delete=models.CASCADE)
    value = models.CharField('valeur', max_length=100)

    def __str__(self):
        return "{}, {}, {}".format(self.food.name, self.nutrient.name, self.value)

Création et application des migrations initiales

$ python manage.py makemigrations
$ python manage.py migrate
$ sqlite3 db.sqlite3
> .schema
...
CREATE TABLE IF NOT EXISTS "foods_food" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(100) NOT NULL, "pict" varchar(300) NULL);
CREATE TABLE IF NOT EXISTS "foods_nutrient" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(100) NOT NULL);
CREATE TABLE IF NOT EXISTS "foods_nutdata" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "value" varchar(100) NOT NULL, "food_id" varchar(100) NOT NULL REFERENCES "foods_food" ("code") DEFERRABLE INITIALLY DEFERRED, "nutrient_id" integer NOT NULL REFERENCES "foods_nutrient" ("id") DEFERRABLE INITIALLY DEFERRED);
...

Interface d’administration

$ cat foods/admin.py
from foods.models import Food, Grp, Nutrient, NutData
from django.contrib import admin

admin.site.register(Food, admin.ModelAdmin)
admin.site.register(Grp, admin.ModelAdmin)
admin.site.register(Nutrient, admin.ModelAdmin)
admin.site.register(NutData, admin.ModelAdmin)

$ python manage.py createsuperuser
...
$ python manage.py runserver

Ouvrir l’url http://localhost:8000/admin

Interaction avec un shell

$ python manage.py shell
>>> from foods.models import Nutrient, Grp
>>> protein = Nutrient(name="Protéines")
>>> protein
Protéines
>>> protein.save()
>>> Nutrient.objects.count()
1

Querysets

Voir: Référence de l’API QuerySet

Tous les aliments dont le nom commence par “Sa” :

list(Food.objects.filter(name__startswith="Sa"))

Tous les aliments dont le nom commence par “Sa” et qui appartiennent au sous-groupe dont le nom est “salades composées et crudités”

list(Food.objects.filter(name__startswith="Sa").filter(ssgrp__name="salades composées et crudités"))

Intégration dans un script

Affiche tous les aliments de la base de données, avec pour chaque aliment la liste de leurs portions

$ cat food_listing.py
import os
import django

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_orm.settings")
django.setup()

# don't import business models before doing `django.setup()`
from foods.models import Food, NutData

for food in Food.objects.all():
    print(food.name)
    for nut_data in NutData.objects.filter(food=food):
        print(">> {}, {}, {}".format(nut_data.food.name, nut_data.nutrient.name, nut_data.value))