Les modèles - models.py

date:2012-05-01 17:52
tags:django, python
category:Django
author:Rémy Hubscher

Le MVT de Django

Le découpage d’une application Django se fait en trois parties :

  1. Le modèle
  2. La vue
  3. Le template

Vous avez déjà eu un léger aperçu de ces trois parties dans le TP précédent.

Le modèle

Django est basé sur un ORM. On va donc créer des objets Python qui vont être capable de se caller automatiquement à une base de données relationnelle.

Cela va nous permettre de faire tourner notre application sur le SGBD de notre choix :

  • SQLite,
  • MySQL,
  • PostgreSQL,
  • Oracle,
  • MSSQL,
  • etc.

Un modèle Django est donc simplement une classe Python qui hérite de django.db.models.Model.

from django.db import models

class Person(models.Model):
    first_name = models.CharField(u'Firstname', max_length=30)
    last_name = models.CharField(u'Lastname', max_length=30)

Les champs disponibles

Il en existe un certain nombre : https://docs.djangoproject.com/en/dev/ref/models/fields/

Certains que vous allez utiliser très souvent, d’autres moins souvent :

  • BooleanField
  • CharField
  • IntegerField
  • DateField
  • DateTimeField
  • EmailField
  • ImageField
  • FileField
  • IPAdressField
  • SlugField
  • TextField
  • URLField
  • etc.

Vous allez même parfois devoir en créer pour vos propres besoins.

Chaque champ peut avoir des arguments spécifiques et une fonction de validation spécifique.

Utilisation d’un ModelField

Pour chaque field, il y a des paramètres.

  1. Le premier, commun à tous, est le label
  2. Ensuite on utilise des paramètres nommés spécifiques à chaque field.

Quelques paramètres globaux :

  • unique : Boolean - Permet de spécifier que la valeur est unique (le champ identifie donc la fiche)
  • blank : Boolean - On autorise le champ a être vide
  • null : Boolean - Si le champ est vide, on stocke le champ comme Null - À utiliser pour les champs qui ne sont pas des chaines de caractères si vous acceptez qu’ils soient vides.
  • choices : Tuple - Permet le choix d’une valeur dans une liste définie, éventuellement avec des groupes de choix.
  • default : La valeur par défaut lorsque le champ n’est pas saisie.
  • editable : Boolean - Si on le met à False le champ ne sera pas éditable par l’utilisateur
  • verbose_name : String - Nom du champ pour les utilisateurs
  • help_text : String - En plus du verbose_name permet de définir une explication sur ce que doit contenir le champ.

Il y a d’autres paramètres que vous pouvez trouver dans la documentation.

CharField

C’est une zone de texte simple avec une taille maximale, max_length comprise entre 0 et 255.

S’il vous faut plus, utilisez un TextField.

from django.db import models
from django.utils.translation import ugettext_lazy as _

GENDER_CHOICES = (('Mr',  _('Mister')),
                  ('Mrs', _('Madam')),
                  ('Miss', _('Miss')))

class Person(models.Model):
    gender = models.CharField(_('gender'), max_length=4, choices=GENDER_CHOICES)
    first_name = models.CharField(_('firstname'), max_length=30)
    last_name = models.CharField(_('lastname'), max_length=30)

    def __unicode__(self):
        return u'%s %s %s' % (self.gender, self.first_name, self.last_name)

DateField et DateTimeField

Ces deux champs sont semblable, l’un contient une date et l’autre la date et l’heure.

Deux paramètres intéressant :

  • auto_now : Boolean - Est mise à jour automatiquement dès que l’objet est sauvegardé.
  • auto_now_add : Boolean - Est mise à jour automatiquement lors de la création de l’objet.

Lorsque auto_now ou auto_now_add sont sélectionné editable est automatiquement mis à False et blank à True.

ImageField et FileField

  • upload_to : Le chemin vers lequel enregistrer le fichier dans le MEDIA_ROOT, ce peut aussi être l’adresse d’une fonction (un callable) qui va s’occuper de retourner le nom du fichier.
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.template.defaultfilters import slugify
from django.utils.encoding import smart_str
import os.path

def upload_to_valid_name(prefix_dir):

    def get_valid_name(instance, name):
        root, ext = os.path.splitext(name)
        root = smart_str(slugify(root).replace('-', '_'))
        return os.path.join(prefix_dir, '%s.%s' % (root, ext))

    return get_valid_name

class Firm(models.Model):
    name = models.CharField(_(u'name'), max_length=50,
                            help_text=_(u"Enter the name of the firm"))
    image = models.ImageField(_(u'logo'),
                              upload_to=upload_to_valid_name('uploads/logo'),
                              null=True, blank=True)

    def __unicode__(self):
        return u'%s' % self.name

La méthode __unicode__

La méthode __unicode__ permet de définir le nom de l’instance de l’objet.

Elle est utilisé notamment lorsqu’on fait un print de l’objet.

La class Meta

Elle permet de définir des informations sur l’objet.

Notamment le verbose_name qui définit le nom de l’objet et le ordering qui définit l’ordre de tri par défault des objets.

from django.db import models
from django.utils.translation import ugettext_lazy as _

GENDER_CHOICES = (('Mr',  _('Mister')),
                  ('Mrs', _('Madam')),
                  ('Miss', _('Miss')))

class Person(models.Model):
    gender = models.CharField(_('gender'), max_length=4, choices=GENDER_CHOICES)
    first_name = models.CharField(_('firstname'), max_length=30)
    last_name = models.CharField(_('lastname'), max_length=30)

    def __unicode__(self):
        return u'%s %s %s' % (self.gender, self.first_name, self.last_name)

    class Meta:
        verbose_name = _('person')
        verbose_name_plural = _('people')
        ordering = ['last_name', 'first_name']

Autres méthodes

Voici quelques informations intéressante, vous pouvez aussi ajouter les méthodes que vous souhaites à vos objets, pour retourner l’âge à partir de la date de naissance par exemple.

from datetime import date

from django.db import models
from django.utils.translation import ugettext_lazy as _

class Person(models.Model):
    name = models.CharField(_('name'), max_length=60,
                            help_text=_('Enter the person full name'))
    dob  = models.DateField(_('date of birth'))

    def __unicode__(self):
        return u'%s' % self.name

    def age(self):
        today = date.today()
        num_years = int((today - self.dob).days / 365.2425)
        return num_years

Lors de l’utilisation :

$ python manage.py shell
>>> from person.models import Person
>>> from datetime import date
>>> me = Person(name=u'Rémy Hubscher', dob=date(1987, 2, 21))
>>> print me
Rémy Hubscher
>>> me.age()
25

Conclusion

Voici donc un bref aperçu des modèles.

Une fois le modèle fait, il faut le créer dans la base de données

$ python manage.py syncdb

Vous pouvez aussi utiliser django-south pour gérer la modification de vos modèles sans perdre les données qui sont dedans.