Annexe B: Référence de la définition de modèle
Le chapitre 5 explique les bases de la définition des modèles, et nous les utilisons tout au long du livre. Il y a, cependant, un énorme choix d’options de modèle disponible qui n’est pas abordé par ailleurs. Cette annexe détaille chaque option de la définition de modèle possible.
Remarquez que même si ces APIs sont considérées comme très stables, les développeurs de Django ajoutent constamment de nouveaux raccourcis et améliorations à la définition de modèle. C’est une bonne idée de toujours vérifier la dernière documentation en ligne à l’adresse http://www.djangoproject.com/documentation/0.96/model-api/.
Champs
La partie la plus importante d’un modèle - et la seule partie nécessaire d’un modèle - est la liste des champs de la base de données quelle défini.
Restrictions sur le nom d’un champ
Django place seulement deux restrictions aux noms d’un champ de modèle.
1.Un nom de champ ne peut être un mot réservé par Python, parce que cela générerait une erreur de syntaxe Python, par exemple:
class Example(models.Model): pass = models.IntegerField() # 'pass' est un mot réservé!2.Le nom d’un champ ne peut contenir plus d’un caractère souligné à suivre, à cause de la façon dont fonctionne sous Django la syntaxe d’une requête de recherche, par exemple:
class Example(models.Model): foo__bar = models.IntegerField() # 'foo__bar' à deux caractères soulignés consécutifs!
Ces limitations peuvent être cependant contournées, puisque votre nom de champ ne doit pas nécessairement correspondre au nom de colonne dans la base. Lisez le «db_column» qui suit.
Les mots SQL réservés, tels que join, where, or select, sont autorisés comme noms de champ de modèle, parce que Django reprend tous les noms de table et tous les noms de colonne dans chaque requête SQL sous-jacente. Elle utilise la syntaxe de guillemets correspondant à votre moteur particulier de base de données.
Chaque champ dans votre modèle doit être une instance de la classe Field appropriée. Django utilise les types de classe de champ pour déterminer quelques petites choses:
- Le type de colonne de la base de données (par exemple, INTEGER, VARCHAR).
- Le widget à utiliser dans l’interface d’administration de Django, si vous prenez soin de l’utiliser (par exemple, <input type="text">, <select>).
- Les prérequis minimum de validation, qui sont utilisé dans l’interface d’administration de Django.
Une liste complète des classes de champs suit, triée alphabétiquement. Notez que les champs relationnels (ForeignKey, etc.) sont abordés dans la section suivante.
AutoField
un IntegerField qui s’auto incrémente selon les IDs disponibles. Vous n’aurez généralement pas besoin de l’utiliser directement; un champ de clef primaire sera automatiquement ajouté à votre modèle si vous n’en précisez pas un.
BooleanField
Un champ true/false (Vrai/Faux).
CharField
Un champ de chaîne de caractère, de petite ou grande taille. Pour de grande quantité de texte, utilisez TextField.
CharField possède un argument supplémentaire, maxlength, qui est la longueur maximale (en nombre de cacractères) du champ. Cette taille maximale est répercutée au niveau de la base de données et dans la validation de Django.
CommaSeparatedIntegerField
Un champ d’entiers séparés par des virgules. Tout comme dans CharField, l’argument maxlength est requis.
DateField
Un champ de date. DateField possède quelques arguments supplémentaires, comme le montre le tableau B-1.
Table B-1. Extra DateField Options
| Argument | Description |
| auto_now | Fixe automatiquement le champ à «now» (maintenant) à chaque fois que l’objet est appelé. C’est pratique pour la marque temporelle «last-modified». Notez que la date courante est toujours utilisée; ce n’est pas une simple valeur par défaut que vous pouvez contourner. |
| auto_now_add | fixe automatiquement le champ à «now» la première fois que l’objet est créer. C’est pratique pour le marquage temporel (timestamp). Notez que la date courante est toujours utilisée; ce n’est pas une simple valeur par défaut que vous pouvez contourner. |
DateTimeField
Un champ de date et d’heure. Il accepte les même options que DateField.
EmailField
Un CharField qui contrôle si la valeur est une adresse électronique valide. Il n’accepte pas maxlength; Sa maxlength (taille maximale) est automatiquement fixée à 75.
FileField
Un champ de téléchargement de fichier. Il prend un argument obligatoire, comme le montre le tableau B-3.
Table B-2. Extra FileField Option
| Argument | Description |
| upload_to | Un chemin du système de fichier local qui sera ajouté à votre paramètre MEDIA_ROOT afin de déterminer la sortie de la fonction d’aide get_<fieldname>_url(). |
Ce chemin peut contenir le formatage strftime (lisez http://www.djangoproject.com/r/python/strftime/), qui sera remplacé par la date/heure du chargement de fichier (afin que les fichiers rapatriés ne remplissent pas le répertoire donné).
Utilisé un FileField ou un ImageField dans un modèle nécessite quelques étapes:
- Dans votre fichier de paramètrage, vous devrez définir dans MEDIA_ROOT le chemin complet vers un répertoire où vous voudriez que Django place les fichiers rapatriés. (Pour des raisons de performances, ces fichiers ne sont pas stockés dans la base de données). Puis définir dans MEDIA_URL la base de l’URL public pour ce répertoire. Assurez vous que l’écriture dans ce répertoire soit permise au compte utilisateur «serveur web».
- Ajoutez le FileField ou le ImageField à votre modèle, en vous assurant de définir l’option upload_to pour indiquer à Django vers quel sous-répertoire de MEDIA_ROOT il devra rapatrier les fichiers.
- Ce qui sera effectivement stocké dans votre base de données est en fait un chemin vers ce fichier (relatif à MEDIA_ROOT). Vous préférerez sans doute utiliser le raccourci de la fonction get_<fieldname>_url fourni par Django. Par exemple, si votre ImageField s’appelle mug_shot, vous pouvez obtenir l’URL absolut vers votre image dans un gabarit grâce à {{object.get_mug_shot_url }}.
Par exemple, admettons que votre MEDIA_ROOT soit fixé à '/home/media', et que upload_to équivale à 'photos/%Y/%m/%d'. La partie '%Y/%m/%d' de upload_to est un formatage strftime; '%Y' est l’année sur quatre chiffres, '%m' est le mois sur deux chiffres, et '%d' est le jour sur deux chiffres. Si vous téléchargez un fichier le 15 janvier 2007, il sera conservé dans le répertoire en tant que /home/media/photos/2007/01/15.
Si vous voulez récupérer le nom du fichier rapatrié sur le système de fichier, ou bien un URL qui se réfère à se fichier, ou encore la taille du fichier, vous pouvez utiliser les méthodes get_FIELD_filename(), get_FIELD_url(), et get_FIELD_size(). Consultez l’annexe C pour une exploration complète de ces méthodes.
Note
À chaque fois que vous avez à faire avec des fichiers rapatriés, vous devriez faire particulièrement attention à l’endroit où vous les placez et au type de fichier dont il s’agit, pour éviter les failles de sécurité. Validez tous les fichiers rapatriés de façon à vous assurez que les fichiers soient ce que vous penser qu’ils soient.
Par exemple, si vous laissez aveuglément quelqu’un placer des fichier, sans validation, dans un répertoire à la racine de votre serveur web, alors il est possible de rapatrier un script CGI ou PHP puis d’exécuter ce script en visitant son URL sur votre site. Ne laisser pas ceci arriver!
FilePathField
Un champ dont les choix sont limité aux noms de fichier d’un certain répertoire du système de fichier. Il accepte trois arguments spéciaux, comme le montre la figure B-4;
Table B-3. Extra FilePathField Options
| Argument | Description |
|---|---|
| path | Requis; le chemin absolu vers un répertoire où le FilePathField doit faire ses choix (par exemple, "/home/images"). |
| match | Optionnel; une expression rationnelle, sous forme de chaîne, qu’utilisera FilePathField pour filtrer les noms de fichier. Notez que cette regex sera appliquée sur la base du nom de fichier, et non pas sur le chemin complet (par exemple, "foo.*\.txt^", entrera en correspondance avec foo23.txt, mais pas bar.txt ou foo23.gif). |
| recursive | Optionnel; Soit True ou False. Par défaut, False. Spécifie si tous les sous répertoires de path doivent être inclus. |
Bien sur, ces arguments peuvent être utilisés conjointement.
Le seul piège potentiel est que cette correspondance ne s’applique qu’à la base du nom de fichier, et pas au chemin complet. Ainsi, par exemple:
FilePathField(path="/home/images", match="foo.*", recursive=True)
validera /home/images/foo.gif mais pas /home/images/foo/bar.gif parce que le filtre s’applique à la base du nom de fichier (foo.gif et bar.gif).
FloatField
Un nombre à virgule flottante, représenté en Python par une instance float. Deux arguments sont requis, comme le montre le Tableau B-2.
Table B-4. Extra FloatField Options
| Argument | Description |
|---|---|
| max_digits | Le nombre maximum de chiffres autorisés dans la partie décimale. |
| decimal_places | Le nombre de partie décimale à stocker avec le nombre |
Par exemple, pour stocker les nombres supérieurs à 999 avec une résolution de deux parties décimales, vous devez faire comme suit:
models.FloatField(..., max_digits=5, decimal_places=2)
Et pour stocker des nombres jusqu’à approximativement 1 milliard avec une résolution de 10 parties décimales, vous utiliserez ceci:
models.FloatField(..., max_digits=19, decimal_places=10)
ImageField
Similaire à FileField, mais valide que l’objet rapatrié est une image valide. Accepte en option deux arguments supplémentaires, height_field et width_field, qui, si définis, seront automatiquement remplis par la largeur et hauteur de l’image à chaque sauvegarde de l’instance du modèle.
En complément des méthodes spéciales get_FIELD_* qui sont disponibles pour FileField, un ImageField possède aussi les méthodes get_FIELD_height() et get_FIELD_width(). Ceci est documenté dans l’annexe C.
ImageField repose sur Python Imaging Library (http://www.pythonware.com/products/pil/).
IntegerField
un entier.
IPAddressField
une adresse IP, sous forme de chaîne de caractères (par exemple, "24.124.1.30").
NullBooleanField
Similaire à BooleanField, mais autorise None/NULL comme l’une des options possible. Utilisez ceci au lieu d’un BooleanField avec null=True.
PhoneNumberField
Un CharField qui vérifie que la valeur correspond à un numéro de téléphone validant le style Américain. (au format XXX-XXX-XXXX).
Note
Si vous devez représenter un numéro de téléphone pour un autre pays, vérifiez le paquet django.contrib.localflavor pour voir si les définitions de champ pour votre pays sont incluses.
PositiveIntegerField
Similaire à IntegerField, mais doit être positif.
PositiveSmallIntegerField
Similaire à PositiveIntegerField, mais autorise des valeurs jusqu’à un certain seuil. La valeur maximale autorisée par ces champs dépend de la base de données, et puisque les bases de données ont un champ pour les entiers court sur 2 octets, la valeur positive maximale pour un entier court est 65 535.
SlugField
«Slug» est un terme de presse écrite (ndt: anglosaxonne). Un «*slug*» est une courte étiquette sur un sujet, contenant uniquement des lettres, des nombres, des soulignements ou trait d’union. Ils sont généralement utilisés dans les URLs.
Similaire à CharField, où vos pouvez préciser maxlength. Si maxlength est spécifié, Django utilisera par défaut une taille de 50.
Un SlugField implique db_index=True puisque l’utilisation primaire des «slugs» concerne les recherches dans les bases de données.
SlugField accepte une option supplémentaire, prepopulate_from, qui est une liste de champs à partir desquels remplir le «slug», à l’aide de Javascript, dans le formulaire d’administration de l’objet:
models.SlugField(prepopulate_fpom=("pre_name", "name"))
prepopulate_from n’accepte pas les noms DateTimeField pour arguments.
SmallIntegerField
Similaire à IntegerField, mais autorise seulement les valeurs dans une certaine fourchette dépendante de la base de données (habituellement but only allows values in a certain database- dependent range (usually -32,768 to +32,767).
TextField
Un champ texte de taille illimitée.
TimeField
Une heure de la journée. Accepte les mêmes options de garniture automatique que DateField et DateTimeField.
URLField
Un champ d’URL. Si l’option verify_exists est à True (par défaut), l’existance de l’URL donné sera vérfiée (c’est à dire que l’URL répond et ne retourne pas une réponse 404).
Comme les autres champs de caractères, URLField accepte l’argument maxlength. Si vous ne précisez pas maxlength, 200 est utilisé par défaut.
USStateField
Une abbréviation sur deux lettres des états Américains.
Note
Si vous devez représenter d’autre pays ou états, regardez d’abord dans le module django.contrib.localflavor pour voir si Django n’inclu pas déjà les champs pour vos locales.
XMLField
Un TextField qui vérifie que la valeur est du XML valide correspondant à un schéma donné. L’argument schema_path est requis, et représente le chemin sur le système de fichier vers un schéma RELAX NG (http://www.relaxng.org/) auprès duquel on valide le champ.
Nécessite jing (http://thaiopensource.com/relaxng/jing.html) pour valider le XML.
Universal Field Options
Les arguments suivants sont disponibles pour chaque type de champ. Tous sont optionnels.
null
Si True, Django stockera la valeur vide en tant que NULL dans la base de données. Par défaut à False.
Notez que les valeurs de chaînes vides seront toujours stockée sous forme de chaîne vide, pas en tant que NULL. Utilisez null=True uniquement pour les champs autres que ceux de chaîne de caractères tels que entiers, Booléens et dates. Pour les deux types de champs, vous devrez aussi préciser blank=True si vous désirez autoriser des valeurs vides dans les formulaires, car le paramètre null affecte uniquement le stockage en base de données ( consultez la partie suivante, intitulée «blank»).
Évitez d’utiliser null sur les champs basés sur les chaînes tels que CharField et TextField à moins d’avoir une excellente raison. Si un champ de ce type contient null=True, cela signifie qu’il à deux valeurs possibles pour l’absence de donnée: NULL et chaîne vide. Dans la plupart des cas, il est redondant d’avoir deux valeurs possibles pour les «non données»; La convention sous Django est d’utiliser la chaîne vide, et non pas NULL.
blank
Si True, le champ peut être vide. Placée à False par défaut.
Notez que cela est différent de null. null est purement relatif à la base de données, alors que blank est relatif à la validation. Si un champ propose blank=True, la validation du site d’administration de Django autorisera la saisie d’une valeur vide. Si un champ propose blank=False, le champ sera requis.
choices
Un itérable (par exemple , une liste, un tuple, ou tout autre objet Python itérable) de deux tuples à utiliser pour les choix de ce champ.
S’il est précisé, l’interface d’administration de Django utilisera une boîte de selection à la place du champ texte standard et limitera les choix à ceux indiqués.
Une liste de selection ressemble à ceci:
YEAR_IN_SCHOOL_CHOICES = (
('FR', 'Freshman'),
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
('GR', 'Graduate'),
)
Le premier élément de chaque tuple est l’actuelle valeur à être stockée. Le second élément est le nom humainement lisible de l’option.
Les choix de la liste peuvent être aussi définis comme une partie de votre modèle de classe:
class Foo(models.Model):
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
gender = models.CharField(maxlength=1,
choices=GENDER_CHOICES)
ou à l’exterieur de votre modèle de classe:
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
class Foo(models.Model):
gender = models.CharField(maxlength=1,
choices=GENDER_CHOICES)
Pour chaque champ du modèle ayant des choices fixés, Django ajoutera une méthode pour récupérer le nom humainement lisible pour le champ de la valeur courante. Consultez l’annexe C pour plus de détails.
db_column
Le nom de colonne relatif à ce champ dans la base de données . S’il n’est pas indiqué, Django utilisera le nom du champ. Ceci est pratique lorsque vous définissez un modèle autour d’une base de données qui existe déjà.
Si le nom de colonne dans votre base de données est un mot réservé par SQL, ou s’il contient des caractères qui ne sont pas autorisés dans les noms de variable en Python (notamment le tiret), cela fonctionne. Django gère les noms de colonne et de table en coulisse.
db_index
Si True, Django créera un index de base de données sur cette colonne lors de la création de table (c’est à dire, lorsque se lance manage.py syncbd).
default
La valeur par défaut pour le champ.
editable
Si False, le champ ne sera pas éditable dans l’interface d’admin ou via le traitement par formulaire. Par défaut à True.
help_text
Texte d’«aide» additionnel qui s’affichera sous le champ dans le formulaire d’administration de l’objet. Ceci est pratique pour la documentation même si votre objet ne possède pas de formulaire d’administration.
primary_key
Si True, le champ est la clef primaire du modèle.
Si vous ne précisez pas primary_key=True dans les champs de votre modèle, Django ajoutera automatiquement ce champ:
id = models.AutoField('ID', primary_key=True)
Ainsi, vous n’avez pas besoin de préciser primary_key=True sur les champs à moins que vous ne vouliez outrepasser le comportement par défaut de la clef primaire.
primary_key=True implique blank=False, null=False, et unique=True. Une seule clef primaire est autorisée sur un objet.
radio_admin
Par défaut, l’administration de Django utilise l’interface «boîte de selection» (<select>) pour les champs qui sont ForeignKey (clef étrangère) ou qui précisent des choices (choix). Si radio_admin est à True, Django utilisera à la place une interface «bouton radio».
N’utilisez pas cela pour un champ à moins qu’il soit ForeignKey ou qu’il précise des choices.
unique
Si True, la valeur pour ce champ doit être unique dans toute la table.
unique_for_date
Fixe le nom d’un DateField ou d’un DateTimeField pour imposé que ce champ soit unique pour la valeur du champ date, par exemple:
- ::class Story(models.Model):
- pub_date = models.DateTimeField() slug = models.SlugField(unique_for_date=”pub_date”) …
Dans le code précédent, DJango n’autorisera pas la création de deux histoires ayant le même slug à la même date. Ceci diffère de l’utilisation de la contrainte unique_together du fait que seule le champ «date de publication» pub_date est pris en compte; la date n’importe pas. FIXME
unique_for_month
Similaire à unique_for_date, mais nécessite un champ unique concernant le mois du champ indiqué.
unique_for_year
Similaire à unique_for_date et unique_for_month, mais pour une année entière.
verbose_name
Chaque type de champ, mis à part ForeignKey, ManyToManyField, et OneToOneField, prends optionnellement un premier argument positionnel - un nom significatif. Si le signifiant n’est pas précisé, Django le créera automatiquement en utilisant le nom de l’attribut du champ, convertissant les caractères soulignés en espaces au passage.
Dans cet exemple, le nom significatif est "Person's first name":
first_name = models.CharField("Person's first name", maxlength=30)
Dans cet exemple, le nom significatif est "first name":
first_name = models.CharField(maxlength=30)
ForeignKey, ManyToManyField, ainsi que OneToOneField imposent que le premier argument soit un modèle de class, il faut donc utiliser l’argument mot-clef verbose_name :
poll = models.ForeignKey(Poll, verbose_name="the related poll") sites = models.ManyToManyField(Site, verbose_name="list of sites") place = models.OneToOneField(Place, verbose_name="related place")
La convention est de ne pas mettre la première lettre d’un verbose_name en lettre capitale. Django changera automatiquement la première lettre au bénéfice d’une capitale si besoin est.
Relationships
Clairement, la puissance des bases de données relationnelles réside dans la relation des tables entre elles. Django permet de définir les trois types de relations les plus courants en matière de base de données: un-à-plusieur, plusieur-à-plusieur et un-à-un.
Cependant, la sémantique des relations un-à-un étant en cours de révision à l’heure d’impression de ce livre, elle n’est donc pas couverte dans ce paragraphe. Vérifier la documentation en ligne pour les dernières nouveautés.
Relations un-à-plusieurs
Pour définir une relation un-à-plusieurs, utilisez ForeignKey. Vous l’utiliserez comme tout autre type de champ Field: en l’incluant comme un attribut de classe de votre modèle.
ForeignKey nécessite une argument positionnel: la classe à laquelle le modèle est relié.
Par exemple, si un modèle Car à un Manufacturer - autrement dit, un Manufacturer fabrique de multiples voitures mais chaque Car à un seul Manufacturer - utilisez les définitions suivantes:
class Manufacturer(models.Model):
...
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer)
...
Pour créer une relation recursive - un objet qui propose une relation un-à-plusieurs avec lui même - utilisez models.ForeignKey('self'):
class Employee(models.Model):
manager = models.ForeignKey('self')
Si vous avez besoin de créer une relation sur un modèle qui n’a pas encore été défini, vous pouvez utiliser le nom d’un modèle, plutôt que l’objet modèle en lui-même:
class Car(models.Model):
manufacturer = models.ForeignKey('Manufacturer')
...
class Manufacturer(models.Model):
...
Notez, cependant, que vous pouvez utiliser uniquement des chaînes de caractères pour vous référer aux modèles provenant d’un même fichier - vous ne pouvez pas utiliser une chaîne de caractère pour référencer un modèle dans une application différente, ou pour référencer un modèle qui à été importé d’ailleurs.
En coulisse, Django ajoute "_id" au nom du champ pour créer le nom de sa colonne en base de données. Dans l’exemple précédent, la table de la base de données relative au modèle Car aura une colonne manufacturer_id. (Vous pouvez changer cela explicitement en précisant db_column; consultez la partie «db_column» qui suit). Cependant, votre code ne doit jamais avoir à gérer le nom de de colonne de la base de données, à moins que vous n’écriviez du SQL personnalisé. Vous aurez toujours affaire aux noms des champs de votre modèle d’objet.
Il est conseillé, mais pas obligatoire, que le nom d’un champ ForeignKey (manufacturer dans notre exemple) soit le nom du modèle, en bas de casse. Vous pouvez, bien sûre, appeller le champ comme bon vous semble, par exemple:
class Car(models.Model):
company_that_makes_it = models.ForeignKey(Manufacturer)
# ...
Les champs ForeignKey prennent un certain nombre d’arguments supplémentaires pour définir la fçon dont la relation doit fonctionner (consultez le tableau B-5). Tous sont optionnels.
Table B-5. ForeignKey Options
| Argument | Description |
|---|---|
| edit_inline | S’il n’est pas définie à False, cet objet relié est édité «en ligne» depuis la page de l’objet relié. Cela signifie que l’objet n’aura pas sa propre interface d’administration. Utilisez soit models.TABULAR soit models.STACKED, qui, respectivement, désigne si les objets éditables en ligne sont affichés sous forme de tableau ou sous forme de «pile» de champs. |
| limit_choices_to | Un dictionnaire d’arguments de recherche et de valeurs (lire l’annexe C) qui limite les choix disponible dans l’administration de cet objet. Utilisez ceci avec les fonctions du module Python datetime pour limiter le choix des objets par date. Par exemple, l’instruction suivante:
limit_choices_to = {'pub_date__lte': datetime.now}
autorise uniquement le choix des objets liés parmi ceux ayant une pub_date antérieure à la date/heure actuellement choisie. À la place d’un dictionnaire, ce peut être un objet Q (voir l’annexe C) pour les requêtes plus complexes. Ceci n’est pas compatible avec edit_inline. |
| max_num_in_admin | Pour les objets édités en ligne, il s’agit du nombre maximum d’objets liés qui s’affichent dans l’interface d’administration. Ainsi, si une pizza ne peut avoir que 10 ingrédients, max_num_in_admin=10 s’assurera qu’un utilisateur n’entre pas plus de dix ingrédients. Notez que cela ne permet pas de s’assurer que plus de dix ingrédients liés n’ont été jamais crées. Le controle s’effectue uniquement au niveau de l’interface d’administration; cela n’agit pas au niveau de l’API Python ou d’une base de données. |
| min_num_in_admin | Le nombre minimum d’objets liés qui s’affichent dans l’interface d’administration. Normalement, lors de la création, les objets en ligne num_in_admin sont affichés, et lors de l’édition, les objets vides num_extra_on_change sont affichés en complément de tous les objets liés pré-existants. Cependant, le seuil min_num_in_admin définit le minimum d’objets liés qui seront affichés. |
| num_extra_on_change | Le nombre d’objet liés correspondant aux champs vides qui faut afficher lors du changement d’état. |
| num_in_admin | Le nombre d’objet en ligne à afficher par défaut sur la page de l’objet lors de l’ajout. |
| raw_id_admin | Affiche seulement un champ pour l’entier à saisir à la place d’un menu déroulant. Ceci est pratique lorsqu’il faut lié un type d’objet qui aura trop de lignes pour faire une boîte de sélection pratique à l’usage. Cela n’est pas utilisé avec edit_inline. |
| related_name | Le nom à utiliser pour la relation entre l’objet lié à celui-ci. Consultez l’annexe C pour plus d’information. |
| to_field | Le champ des objets vers lesquels pointe la relation. Par défaut, Django utilise la clef primaire de l’objet lié. |
Relation plusieurs-à-plusieurs
Pour définir une relation plusieurs-à-plusieurs, utilisez ManyToManyField. Tout comme ForeignKey, ManyToManyField nécessite un argument positionnel: la classe dont le modèle est lié.
Par exemple, si une Pizza a de multiples objets Ingrédients - à savoir qu’un Ingrédient peut être sur de multiples pizzas et que chaque Pizza à de multiples ingrédients - voici comment vous pourriez représenter cela:
class Topping(models.Model):
...
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
...
Comme avec ForeignKey, une relation réflexive peut être défini en utilisant la chaîne 'self' à la place du nom de modèle, et vous pouvez vous référer à un modèle pas encore défini en utilisant une chaîne contenant le nom du modèle. Toutefois, vous ne pouvez utiliser que des chaînes pour vous référer aux modèles d’un même fichier models.py - vous ne pouvez pas utiliser une chaîne pour référencer un modèle dans une application différente, ou pour référencer un modèle qui a été importé depuis un autre endroit.
Il est conseillé, mais pas nécessaire, que le nom d’un ManyToManyField (ingrédients dans notre exemple) soit un terme pluriel décrivant le jeu d’objets relatifs au modèle.
En coulisses, Django créer une jointure de table intermédiaire pour représenté la relation plusieurs-à-plusieurs.
Que le modèle ait un ManyToManyField importe peu, vous en aurez besoin uniquement dans un seul des modèles - pas dans les deux.
Si vous utilisez l’interface d’administration, les instances ManyToManyField doivent aller dans l’objet qui va être édité dans l’interface d’administration. Dans l’exemple précédent, ingrédients est dans Pizza (plutôt qu’un Ingrédient ayant un ManyToManyField pizzas) parcequ’il est plus naturel de penser à une Pizza ayant des ingrédients qu’à un ingrédient présent sur de multiples pizzas. De la façon dont cela est paramétré dans l’exemple, le formulaire d’administration d’une Pizza permettra aux utilisateurs de selectionner les ingrédients.
Les objets ManyToManyField prennent un certain nombre d’arguments supplémentaires pour définir comment la relation doit fonctionner (consulter le Tableau B-6). Tous sont optionnels.
Table B-6. ManyToManyField Options
| Argument | Description |
| related_name | Le nom à utiliser pour la relation depuis l’objet lié vers celui-ci. Consultez l’annexe C pour plus d’information. |
| filter_interface | Utilise dans le formulaire d’administration de l’objet une interface «fitlrante» astucieuse et non-obstructive, en Javascript, à la place de <select multiple>, dont l’usage est contestable. La valeur doit être models.HORIZONTAL ou models.VERTICAL (c’est à dire que l’interface doit être empilée horizontalement ou verticalement). |
| limit_choices_to | Lisez la description dans ForeignKey. |
| symmetrical | Utilisé uniquement dans la définition de ManyToManyField sur self. Considérez le modèle suivant:
Lorsque Django traite ce modèle, il repère qu’il possède un ManyToManyField sur lui même, et conclut qu’il ne doit pas ajouter un attribut person_set à la classe Person. Au lieu de cela, le ManyToManyField est considéré comme étant symétrique - autrement dit, si je suis votre amis, alors vous êtes aussi mon amis. Si vous ne voulez pas de symétrie dans les relations ManyToMany` avec ``self, placez symmetrical à False. Cela obligera Django à ajouter le descripteur pour la relation réflexive, permettant aux relations ManyToMany de ne pas être symétriques. |
| db_table | Le nom de la table à créer pour stocker les données plusieurs-à-plusieurs. Si cela n’est pas précisé, Django utilisera un nom par défaut basé sur les noms des deux tables qui seront jointes. |
Options du modèle de métadonnées
Les métadonnées spécifiques au modèle résident dans une class Meta définie dans le corp de votre modèle de classe:
class Book(models.Model):
title = models.CharField(maxlength=100)
class Meta:
# model metadata options go here
...
Les métadonnées de modèle sont «tout ce qui n’est pas un champs», tel que les options d’ordonnancement et consort.
Les sections qui suivent présentent une liste de toutes les options Meta possibles. Aucune option n’est requise. Ajouter une class Meta à un modèle est totalement optionnel.
db_table
Le nom de la table dans la base de données à utiliser pour le modèle.
Pour épargner votre temps, Django déduit automatiquement le nom de la table de la base de données depuis le nom de votre modèle de classe et de l’application qui la contient. Un nom de modèle de table d’une base de données est construit en concaténant le «label de l’application» du modèle - le nom que vous avez utilisez pour manage.py startapp - avec le nom du modèle de classe, avec un soulignement entre les deux. FIXME
Par exemple, si vous avez une application livres (créé par manage.py startapp livres), un modèle défini comme class Livre aura une table dans la base de données appelée livres.
Pour outrepasser le nom de la table en base de données, utilisez le paramètre db_table dans la class Meta:
class Book(models.Model):
...
class Meta:
db_table = 'things_to_read'
Si rien n’est précisé, Django utilisera app_label + '_' + model_class_name. Consultez See the section ?Table Names? for more information.
Si le nom de votre base de données est un mot réservé par SQL, ou s’il contient des caractères qui ne sont pas autorisés dans les nom de variable Python (notamment le tiret), cela fonctionne. Django gère les noms de colonne et de table en coulisse.
get_latest_by
Le nom d’un DateField ou d’un DateTimeField dans le modèle. Cela précise le champ par défaut à utiliser dans la méthode latest() de votre modèle Manager.
Voici un exemple:
class CustomerOrder(models.Model):
order_date = models.DateTimeField()
...
class Meta:
get_latest_by = "order_date"
Consultez l’annexe C pour en savoir plus sur la méthode latest().
order_with_respect_to
Marque cet objet comme étant «ordonnalbe» respectivement au champ indiqué. Ceci est pratiquement toujours utilisé avec les objets liés pour leur permettre d’être ordonnés selon un objet parent. Par exemple, si une Réponse se réfère à un objet Question, et si une question à plus d’une réponse, et que l’ordre des réponses importe, vous feriez ceci:
class Réponse(models.Model):
question = models.ForeignKey(Question)
# ...
class Meta:
order_with_respect_to = 'question'
ordering
L’ordonnancement de l’objet par défaut, à utiliser pour obtenir des listes d’objets:
class Book(models.Model):
title = models.CharField(maxlength=100)
class Meta:
ordering = ['title']
Il s’agit d’un tuple ou d’une liste de chaînes. Chaque chaîne est un nom de champ avec un préfix - optionnel, qui indique un ordre décroissant. Les champs sans - initial seront ordonnés dans l’ordre croissant. Utilisez la chaîne "?" pour un ordre aléatoire.
Par exemple, pour classer un champ titre selon un odre croissant (c’est à dire de A à Z), utilisez ceci:
ordering = ['title']
Pour classer selon le titre dans un ordre décroissant (c’est à dire de Z à A), utilisez ceci:
ordering = ['-title']
Pour classer le titre selon un ordre décroissant, puis ensuite l’auteur selon un ordre croissant, faîtes ceci:
ordering = ['-title', 'author']
Notez que, quelque soit le nombre de champs présent dans ordering, le site d’administration utilisera uniquement le premier champ.
permissions
Autorisations additionnelles pour avoir accès à la table des permissions lorsque l’on créer cet objet. Les autorisations d’ajout, de suppression et de modification sont automatiquement crées pour chaque objet dont l’admin est précisé. Cet exemple spécifie un autorisation supplémentaire, peut_divrer_des_pizzas:
class Employé(models.Model):
...
class Meta:
permissions = (
("peut_livrer_des_pizzas", "Peut livrer des pizzas"),
)
Il s’agit d’une liste ou d’un tuple de deux tuples au format (permission_code, nom_humainement_lisible).
Consultez le chapitre 12 pour plus de détails sur les permissions.
unique_together
Jeu de noms de champ qui, pris ensemble, doit être unique:
class Employee(models.Model):
department = models.ForeignKey(Department)
extension = models.CharField(maxlength=10)
...
class Meta:
unique_together = [("department", "extension")]
Il s’agit d’une liste de listes de champs qui doit être unique lorsque l’on considère l’ensemble. C’est utilisé dans l’interface d’administration de Django et forcé au niveau de la base de données (c’est à dire que les intructions UNIQUE appropriées sont incluses dans l’instruction CREATE TABLE).
verbose_name
Un nom humainement lisible pour un objet, au singulier:
class CustomerOrder(models.Model):
order_date = models.DateTimeField()
...
class Meta:
verbose_name = "order"
Si rien n’est précisé, Django utilisera une version adaptée du nom de la classe dans lequel Camelcase devient camel case.
verbose_name_plural
Le nom pluriel de l’objet:
class Sphynx(models.Model):
...
class Meta:
verbose_name_plural = "sphynges"
Si rien n’est précisé, Django ajoutera un «s» au verbose_name.
Managers
Un Manager est une interface au travers de laquelle les opération de requête de base de données sont fournies aux modèles Django. Au moins un Manager exist pour chaque modèle d’une application Django.
La façon dont fonctionne les classes Manager est documentée dans l’annexe C. Cette partie classes work is documented in Appendix C. Cette section aborde spécifiquement les options de modèle qui personnalisent le comportement du Manager.
Manager Names
Par défaut, Django ajoute un Manager avec le nom des objects à chaque modèle de classe Django. Cependant, si vous voulez utiliser les objects en tant que nom de champ, ou si vous voulez utiliser un autre nom que celui des objects pour le Manager, vous pouvez les renommer sur la base d’un par modèle. Pour renommer le Manager d’une classe donnée, définissez un attribut de classe de type models.Manager() sur ce modèle, par exemple:
from django.db import models
class Person(models.Model):
...
individu = models.Manager()
En utilisant cet exemple de modèle, Person.objects générera une exception AttributeError (puisque Person ne possède pas d’attribut objects), alors que Person.individu.all() fournira une liste de tous les objets Person.
Custom Managers
Vous pouvez utiliser un Manager personnalisé dans un modèle en étendant la base de la classe Manager et en instanciant votre Manager personnalisé dans votre modèle.
Il y a deux raisons pour lesquelles vous pourriez vouloir personnaliser un Manager: pour ajouter des méthodes Manager, ou pour modifier le QuerySet initial que le Manager retourne.
Ajouter des méthodes supplémentaires au Manager
Ajouter des méthodes Manager supplémentaires est la meilleure façon d’ajouter des fonctionnalités «au niveau des tables» à vos modèles. (Pour des fonctionnalités «au niveau des lignes» - c’est à dire pour les fonctions qui agissent sur une seule instance d’un modèle d’objet - utilisez les mèthodes de modèle (voir ci-après), et non pas les méthodes personnalisées de Manager).
Une méthode personnalisée de Manager peut renvoyer tout ce que vous voulez. Elle n’a pas besoin de nécessairement renvoyer un QuerySet.
Par exemple, ce Manager personnalisé offreune méthode with_counts(), qui renvoie une liste de tous les objets OpinionPoll, chacun ayant un attribut num_responses additionnel qui est le résultat d’un agrégat de requête:
from django.db import connection
class PollManager(models.Manager):
def with_counts(self):
cursor = connection.cursor()
cursor.execute("""
SELECT p.id, p.question, p.poll_date,
COUNT(*)
FROM polls_opinionpoll p, polls_response r
WHERE p.id = r.poll_id
GROUP BY 1, 2, 3
ORDER BY 3 DESC""")
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], question=row[1],
poll_date=row[2])
p.num_responses = row[3]
result_list.append(p)
return result_list
class OpinionPoll(models.Model):
question = models.CharField(maxlength=200)
poll_date = models.DateField()
objects = PollManager()
class Response(models.Model):
poll = models.ForeignKey(Poll)
person_name = models.CharField(maxlength=50)
response = models.TextField()
Avec cet exemple, vous utiliserez OpinionPoll.objects.with_counts() pour renvoyer cette liste d’objet OpinionPoll avec les attributs num_responses.
Un autre chose à noter au sujet de cet exemple est que les méthodes Manager peuvent accéder à self.model afin d’obtenir le modèle de classe auquelles elles sont attachées.
Modifier les Manager QuerySets initiaux
Un QuerySet de base du Manager renvoie tous les abjets présent dans le système. Par exemple, en utilisant ce modèle:
class Book(models.Model):
title = models.CharField(maxlength=100)
author = models.CharField(maxlength=50)
l’instruction Book.objects.all() retournera tous les livres de la base de données.
Vous pouvez outrepasser le QuerySet de base en redéfinissant la méthode Manager.get_query_set(). get_query_set() doit retourner un QuerySet avec les propriétés que vous avez demandé.
Par exemple, le modèle suivant possède deux managers - un qui retourne tous les objets, et un qui renvoie seulement les livres de Roald Dahl:
# First, define the Manager subclass.
class DahlBookManager(models.Manager):
def get_query_set(self):
return super(DahlBookManager,
self).get_query_set().filter(author='Roald Dahl')
# Then hook it into the Book model explicitly.
class Book(models.Model):
title = models.CharField(maxlength=100)
author = models.CharField(maxlength=50)
objects = models.Manager() # The default manager.
dahl_objects = DahlBookManager() # The Dahl-specific manager.
Avec cet exemple de modèle, Book.objects.all() va renvoyer tous les livres de la base de données, alors que Book.dahl_objects.all() renverra uniquement ceux écrits par Roald Dahl.
Bien sur, puisque get_query_set() renvoie un objet QuerySet, vous pouvez utiliser sur celui-ci filter(), exclude(), et toutes les autres méthodes. Ainsi, ces instructions sont valides:
Book.dahl_objects.all() Book.dahl_objects.filter(title='Matilda') Book.dahl_objects.count()
Cet exemple met aussi en valeur une autre technique intéressante: l’utilisation de multiples managers sur le même modèle. Vous pouvez attacher autant d’instances Manager() à un modèle que vous voulez. C’est une façon simple de définir des «filtres» courants pour vos modèles. Voici un exemple:
class MaleManager(models.Manager):
def get_query_set(self):
return super(MaleManager,
self).get_query_set().filter(sex='M')
class FemaleManager(models.Manager):
def get_query_set(self):
return super(FemaleManager,
self).get_query_set().filter(sex='F')
class Person(models.Model):
first_name = models.CharField(maxlength=50)
last_name = models.CharField(maxlength=50)
sex = models.CharField(maxlength=1, choices=(('M', 'Male'),
('F', 'Female')))
individu = models.Manager()
men = MaleManager()
women = FemaleManager()
cette exemple vous permet de appeller Person.men.all(), Person.women.all(), et Person.individu.all(), et de récupérer les résultats prévisibles.
Si vous utilisez des object Manager personnalisés, remarquez que le premier Manager que rencontre Django (dans l’ordre où ils sont définis dansle modèle) à un status spécial. Django interprète le premier Manager défini dansune classe comme étant le Manager par défaut. Certaines opérations - comme le site d’administration de Django - utilisent le Manager par défaut pour obtenir des listes d’objets, c’est donc généralement une bonne idée que le premier Manager ne soit pas filtré. Dans le dernier exemple, l’individu Manager est définie en premier - c’est donc le manager par défaut.
Méthodes de modèle
Définissez des méthodes personnalisées sur un modèle pour ajouter une fonctionnalité «au niveau des lignes» à vos objets. Bien que les méthodes Manager soient destinées à faire des choses impactant toute la table, les méthodes de modèle doivent agir sur une instance particulière du modèle.
C’est une technique intéressante pour conserver la logique métier à un seul endroit: le modèle. Par exemple, ce modèle possède quelques méthodes personnalisées:
class Person(models.Model):
first_name = models.CharField(maxlength=50)
last_name = models.CharField(maxlength=50)
birth_date = models.DateField()
address = models.CharField(maxlength=100)
city = models.CharField(maxlength=50)
state = models.USStateField() # Yes, this is America-
centric...
def baby_boomer_status(self):
"""Returns the person's baby-boomer status."""
import datetime
if datetime.date(1945, 8, 1) <= self.birth_date <=
datetime.date(1964, 12, 31):
return "Baby boomer"
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
return "Post-boomer"
def is_midwestern(self):
"""Returns True if this person is from the
Midwest."""
return self.state in ('IL', 'WI', 'MI', 'IN', 'OH',
'IA', 'MO')
@property
def full_name(self):
"""Returns the person's full name."""
return '%s %s' % (self.first_name, self.last_name)
La dernière méthode de cet exemple est une property (propriété) - un attribut implémenté par un code personnalisé utilisant les accesseurs/mutateurs.Les «properties» sont une astuce ajoutée à Python 2.2; vous pouvez en savoir plus à leurs sujet en lisant http://www.python.org/download/releases/2.2/descrintro/#property.
Il existe aussi une poignée de méthodes de modèle qui ont une signification «spéciale» pour Python ou Django. ces méthodes sont décrites dans les sections qui suivent.
__str__
__str__() est une «méthode magique»i de Python qui défini ce qui doit être retourné si vous appellez str() sur l’objet. Django utilise str(obj) (ou la fonction relative unicode(obj), décrite succintement) dans de nombreux endroits, plus particulièrement en tant que valeur affichée pour le rendu d’un objet dans le site d’administration de Django et en tant que valeur insérée dans un gabarit lorsqu’il affiche un objet. Vous devez donc toujours renvoyer des chaînes claires, humainement compréhensibles, pour le __str__ de l’objet. Bien que cela ne soit pas obligatoire, cela reste fortement recommandé.
Voici un exemple:
class Person(models.Model):
first_name = models.CharField(maxlength=50)
last_name = models.CharField(maxlength=50)
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
get_absolute_url
Défini une méthode get_absolute_url() pour indiquer à Django comment générer l’URL d’un objet, par exemple:
def get_absolute_url(self):
return "/people/%i/" % self.id
Django utilise cela dans son interface d’administration. Si un objet précise get_absolute_url(), la page d’édition de l’objet proposera un lien «Voir sur le site» qui vous ménera directement sur la vue publique de l’objet, conformément à get_absolute_url().
D’autre parties de Django, tel que le framewxork de syndication de contenu, utilise get_absolute_url() comme un commodité récompensant les personnes qui ont défini la méthode.
Utiliser get_absolute_url() dans les gabarits est une bonne pratique, au lieu de coder en dure l’URL de vos objets. Par exemple, le code de ce gabarit est mauvais:
<a href="/people/{{ object.id }}/">{{ object.name }}</a>
Alors que celui-ci est bon:
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
Le problème avec la façon dont nous venons d’écrire get_absolute_url() est qu’il viole légérement le principe DRY: l’URL de cet objet est défini à la fois dans le fichier URLconf et dans le modèle.
Vous pouvez dissocier vos modèles de l’URLconf en utilisant le décorateur permalink. Ce décorateur est transmis à la vue, une liste de paramètres positionnels, et (optioinnellement) undictionnaire de paramètres nommés. Django génère ensuite le chemin complet de l’URL à partir de l’URLconf, substituant les paramètres que vous avez précisé dans l’URL. par exemple, si votre URLconf contient uneligne telle que celle qui suit:
(r'^people/(\d+)/$', 'people.views.details'),
votre modèle peut avoir une méthode get_absolute_url qui ressemble à ceci:
@models.permalink
def get_absolute_url(self):
return ('people.views.details', [str(self.id)])
De la même façon, si vous avez une entrée de l’URLconf qui ressemble à ceci:
(r'/archive/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$',archive_view)
vous pouvez référencer cela en utilisant permalink() comme suit:
@models.permalink
def get_absolute_url(self):
return ('archive_view', (), {
'year': self.created.year,
'month': self.created.month,
'day': self.created.day})
Remarquez que nous précisons dans ce cas une séquence vide pour le second argument, parce que nous voulons transmettre uniquement les arguments mot-clef, et pas les arguments nommés.
De cette façon, vous liez l’URL absolu du modèle à la vue qui est utilisé pour l’afficher, sans répeter ailleurs les informations relatives à l’URL. Vous pouvez continuer à utiliser la méthode get_absolute_url dans les gabarits, comme avant.
Exécuter du SQL personnalisé
Vous pouvez librement écrire des instructions SQL personnalisées dans vos méthodes de modèle et dans vos méthodes au niveau modules. L’objet django.db.connection représente la connection courante vers la base de données. Pour l’utiliser, appelez connection.cursor() pour obtenir un objet curseur. Ensuite, appelez cursor.execute(sql, [params]) pour exécuter le SQL, et cursor.fetchone() ou cursor.fetchall() pour récupérer les lignes résultantes:
def my_custom_sql(self):
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT foo FROM bar WHERE baz = %s",
[self.baz])
row = cursor.fetchone()
return row
connection et cursor implémentent principalement l’API de base de données standard sous Python (http://www.python.org/peps/pep-0249.html). Si vous n’êtes pas familier avec l’API SGBD de Python, notez que l’instruction SQL dans cursor.execute() utilise les substitutions, "%s", plutôt que d’ajouter des paramètres directement au sein du SQL. Si vous utilisez cette technique, la bibliothèque de la base de données sous jacente ajoutera automatiquement les guillemets et les échappements nécessaires à vos paramètres. (Notez aussi que Django s’attend à une substitution "%s", et non pas "?", qui est utilisé par les liaisons Python SQLite). Ceci dans un soucis de cohérence et de raison.
Un dernière remarque: si tous ce que vous voulez faire est d’utiliser une clause WHERE personnalisée, vous pouvez utiliser simplement les arguments where, tables, et params de l’API de recherche standard. Voyez l’annexe C.
Overriding Default Model Methods
Comme expliqué dans l’annexe C, chaque modèle propose automatiquement quelques méthodes - et plus particulièrement, save() et delete(). Vous pouvez outrepasser ces méthodes pour modifier leur comportement.
Un cas d’utilisation classique pour outrepasser les méthodes primitives est se présente si vous voulez que quelque chose se passe à chaque fois que vous enregistrez un objet, comme par exemple:
class Blog(models.Model):
name = models.CharField(maxlength=100)
tagline = models.TextField()
def save(self):
do_something()
super(Blog, self).save() # Call the "real" save()
method.
do_something_else()
Vopus pouvez aussi empêcher l’enregistrement:
class Blog(models.Model):
name = models.CharField(maxlength=100)
tagline = models.TextField()
def save(self):
if self.name == "Yoko Ono's blog":
return # Yoko shall never have her own blog!
else:
super(Blog, self).save() # Call the "real"
save() method
Options d’administration
La classe Admin indique à Django comment afficher le modèle dans le site d’administration. Les sections qui suivent présentent une liste de toutes les options d’Admin possibles. Aucune de ces options n’est obligatoire. Pour utiliser une interface d’administratino sans préciser d’options, utilisez pass, comme ceci:
class Admin:
pass
Ajouter class Admin à un modèle est totalement optionnel.
date_hierarchy
Initialisez date_hierarchy avec le nom d’un DateField ou d’un DateTimeField dans votre modèle, et la page listant les modifications incluera une navigation basée sur les dates utilisant ce champ.
Voici un exemple:
class CustomerOrder(models.Model):
order_date = models.DateTimeField()
...
class Admin:
date_hierarchy = "order_date"
fields
Initialisez fields pour controler l’aspect des pages «ajouter» et «modifier» de l’interface d’administration.
fields est une structure de données imbriqueés asez complexe dont la démonstration est plus simple avec un exemple. Celuiqui suit est extrait du modèle FlatPage, appartenant à django.contrib.flatpages:
class FlatPage(models.Model):
...
class Admin:
fields = (
(None, {
'fields': ('url', 'title', 'content',
'sites')
}),
('Advanced options', {
'classes': 'collapse',
'fields' : ('enable_comments',
'registration_required', 'template_name')
}),
)
Officiellement, fields est une liste de deux tuples, dans lesquels chacun des deux tuples représente un <fieldset> du formulaire de la page d’administration.(Un <fieldset> est une «section» du formulaire).
Les deux tuples sont au format (name, field_options), où name est une chaîne représetant le titre du fieldset et où field_options est un dictionnaire d’informations au sujet du fieldset, incluant une liste de champs à afficher à l’intérieur de celui-ci.
Si les fields ne sont pas précisés, Django affichera par défaut chaque champ qui n’étant pas un AutoField et ayant editable=True, au sein un unique fieldset, dans le même ordre que celui où sont définis les champs du modèle.
Le dictionnaire field_options peut avoir les clefs décritent dans les sections qui suivent.
fields
Un tuple de noms de champ à afficher dans le fieldset. La clef est requise.
Pour afficher plusieurs champs sur la même ligne, enveloppez ces champs dans leur propre tuple. Dans cet exemple, les champs first_name et last_name seront affichés sur la même ligne:
'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
classes
Une chaîne contenant les classes CSS supplémentaires à appliquer au fieldset.
Appliquez des classes multiples en les séparant par des espaces:
'classes': 'wide extrapretty',
Deux classes utiles définies dans la feuille de style par défaut du site d’administration sont collapse et wide. Les fieldsets avec le style collapse seront initialement pliés dans le site d’administration et remplacés par un petit lien «cliquer pour déployer». Les fieldsets ayant le style wide se verrons ajouter un espace horizontal supplémentaire.
description
Une chaîne de texte supplémentaire et optionnel qui sera affiché en haut de chaque fieldset, en dessous de son en-tête. A string of optional extra text to be displayed at the top of each fieldset, under the heading of the fieldset. Il est utilisé en l’état, vous pouvez donc employer du HTML et vous devez échapper n’importe quel caractère HTML spécial (comme par exemple les esperluettes) vous même.
js
Une liste de chaînes représentant les URLs des fichiers JavaScript files à lier avec l’écran d’administration via les balises <script src="">. Ceci peut être utilisé pour modifier un type donnée de page d’administration en Javascript ou pour fournir des «liens rapides» permettant de remplir avec des valeurs par défaut certains champs.
Si vous utilisez des URLs relatives - c’est à dire, des URLs qui ne commencent pas par http:// ou / - alors le site d’administration préfixera automatiquement ces liens avec settings.ADMIN_MEDIA_PREFIX.
list_display
Fixez list_display pour contrôler les champs qui seront affichés sur la liste des changements de la page d’administration.
Si vous ne précisez pas list_display, le site d’administration affichera une seule colonne utilisant la représentation __str__() de chaque objet.
Voici quelques cas particuliers à noter au sujet de list_display:
Si le champ est un ForeignKey, Django affichera le __str__() relatif à l’objet.
Les champs ManyToManyField ne sont pas supportés, parce que cela entraîne l’exécution d’une requête SQL distincte pour chaque ligne du tableau. Si vous voulez tout de même faire cela, donnez à votre modèle une méthode personnalisée, et ajoutez le nom de cette méthode à list_display. (Plus de détails sur les méthodes personnalisées sous peu, dans list_display).
Si le champ est un BooleanField ou un NullBooleanField, Django affichera une jolie icône «on» ou «off» à la place de True ou False.
Si la chaîne précisée est une méthode du modèle, Django l’appellera et affichera la sortie. Cette méthode doit proposer un attribut de fonction short_description, pour pouvoir l’utiliser dans l’en tête du champ.
Voici un exemple de modèle complet:
class Person(models.Model): name = models.CharField(maxlength=50) birthday = models.DateField() class Admin: list_display = ('name', 'decade_born_in') def decade_born_in(self): return self.birthday.strftime('%Y')[:3] + "0's" decade_born_in.short_description = 'Birth decade'Si la chaîne précisée est une méthode du modèle, Django échaperra la sortie HTML par défaut. Si vous préférez ne pas échapper la sortie de votre méthode, précisez à la méthode un attribut allow_tags dont la valeur est à True.
Voici un exemple complet de modèle:
class Person(models.Model): first_name = models.CharField(maxlength=50) last_name = models.CharField(maxlength=50) color_code = models.CharField(maxlength=6) class Admin: list_display = ('first_name', 'last_name', 'colored_name') def colored_name(self): return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name) colored_name.allow_tags = TrueSi la chaîne précisée est une méthode du modèle qui rencoie True ou False, Django affichera une jolie icône «on» ou «off» si vous ajoutez à la méthode un attribut boolean dont la valeur est à True.
Voici un exemple complet de modèle:
class Person(models.Model): first_name = models.CharField(maxlength=50) birthday = models.DateField() class Admin: list_display = ('name', 'born_in_fifties') def born_in_fifties(self): return self.birthday.strftime('%Y')[:3] == 5 born_in_fifties.boolean = TrueLes méthodes __str__() sont tout aussi valides dans list_display que dans tout autre méthode de modèle, il est donc tout à fait correcte de faire ceci:
list_display = ('__str__', 'some_other_field')Habituellement, les éléements de list_display qui ne sont pas des champs existants de la base de données ne peuvent pas être utilisés dans les tris (parce que Django fait tout le tri au niveau de la base de données).
Toutefois, si un élément de list_display represente un certain champ de la base de données, vouspouvez indiquer ce état de fait en initialisant l’attribut admin_order_field de l’élément, par exemple:
class Person(models.Model): first_name = models.CharField(maxlength=50) color_code = models.CharField(maxlength=6) class Admin: list_display = ('first_name', 'colored_first_name') def colored_first_name(self): return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name) colored_first_name.allow_tags = True colored_first_name.admin_order_field = 'first_name'Le code précédent indiquera à Django d’ordonner le champ first_name lorsqu’il tentera de classer par colored_first_name au sein du site d’admin.
list_display_links
Fixez list_display_links pour controler quels seront les champs dans list_display qui devrons pointer sur la page «modification» d’un objet.
Par défaut, la page lsitant les changements reliera la première colonne - le premier champ spécifié dans list_display - à la page des modifications pour chaque élément. Mais list_display_links vous permet de modifier les colonnes qui seront liées? Initialisez list_display_links avec une liste ou un tuple de noms de champ (au même format que list_display) pour les lier.
list_display_links peut préciser un ou plusieurs noms de champ. Dès lors que les noms de champ apparaissent dans list_display, Django ne se préoccupe pas du nombre (ou du si peu) de champs liés. L’unique prérequis est de définir list_display si vous voulez utiliser list_display_links.
Dans cet exemple, le champ first_name et le champ last_name seront liés sur la page listant les changements:
class Person(models.Model):
...
class Admin:
list_display = ('first_name', 'last_name',
'birthday')
list_display_links = ('first_name', 'last_name')
Finallement, notez que de façon à utiliser list_display_links, vous devez aussi définir list_display.
list_filter
Initialisez list_filter pour activer les filtres dans la barre sur la droite de la page listant les changmeent dans l’interface d’administration. Il doit s’agir d’une liste de noms de champ, et chaque champ spécifié doit être soit un BooleanField, DateField, DateTimeField, ou un ForeignKey.
Cet exemple, extrait du modèle django.contrib.auth.models.User, montre comment list_display et list_filter fonctionnent:
class User(models.Model):
...
class Admin:
list_display = ('username', 'email', 'first_name',
'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser')
list_per_page
Initialisez list_per_page pour contrôler le nombre d’éléments qui apparaissent sur chaque page listant les changements. Par défaut, elle est fixée à 100.
list_select_related
Initialisez list_select_related pour indiquer à Django qu’il doit utiliser select_related() lors de la récupération de la liste des objets de la page d’admin listant les modifications. Ceci peut vous épargner pas mal de requêtes en base de données si vous utilisez les objets liés dans l’affichage de la liste des changements.
La valeur doit être soit True ou False. Elle vaut par défaut False à moins que l’un des champs list_display soit une ForeignKey (clef étrangère).
Pour en savoir plus sur select_related(), lisez l’annexe C.
ordering
Initialisez ordering pour préciser la façon dont les objets de la liste des changements doivent être ordonnés. Ceci doit être une liste ou un tuple du même format que le paramètre ordering du modèle.
Si rien n’est précisé, l’interface d’administration de Django utilisera le classement par défaut du modèle.
save_as
Initialisez save_as à True pour activer la fonctionnalité «enregistrer sous» dans le formulaire d’administration des modifications.
Normalement, les objets ont trois options de sauvegarde: «Enregistrer», «enregistrer et continuer l’édition» et «Enregistrer et ajouter un nouveau». Si save_as est à True, «Enregistrer et ajouter un nouveau» sera remplacer par un bouton «Enregistrer sous».
«Enregistrer sous» signifie que l’objet sera enregistrer en tant que nouvel objet (avec un nouvel ID), plutôt que sous l’ancien objet.
Par défaut, save_as est fixée à False.
save_on_top
Initialisez save_on_top pour ajouter des boutons «Enregistrer» en haut des formulaires d’administration des changements.
Normallement, les boutons d’enregistrement apparaissent uniquement en bas des formulaires. Si vous initialisez save_on_top, les butons apparaitrons à la fois en haut et en bas.
Par défaut, save_on_top est fixée à False.
search_fields
Initialisez search_fields pour activer une boîte de recherche sur la page d’admin de la liste des changements. Ceci doit être fait par une liste de noms de champ qui seront explorés chaque fois que quelqu’un soumettra une requête dans cet boîte de saisie textuelle.
Ces champs doivent être des champs textuels, tel que CharField ou TextField. Vous pouvez aussi faire des recherche liées sur une ForeignKey avec la notation de l’API de recherche qui suit:
class Employee(models.Model):
department = models.ForeignKey(Department)
...
class Admin:
search_fields = ['department__name']
Lorsque quelqu’un effectue une recherche dans la boîte de requête de l’interface d’admin, Django découpe la requête en mots et retourne tous les objets qui contiennent chacun des mots, sans tenir compte de la casse, et où chaque mot doit être au moin dans l’un des search_fields. Par exemple, si search_fields est initialisée à ['first_name', 'last_name'] et qu’un utilisateur recherche john lennon, Django effectuera l’équivalent de cette clause SQL WHERE:
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
Pour des recherches plus rapides ou plus restrictives, préfixez le nom du champ avec un opérateur, comme le montre le Tableau B-7.
Table B-7. Operators Allowed in search_fields
| Signification des opérateurs | |
|---|---|
| ^ | Correspond au début du champ. Par exemple, si search_fields vaut ['^first_name', '^last_name'], et qu’un utilisateur recherche john lennon, Django effectuera l’équivalent de cette clause SQL WHERE: WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%') AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%') cette requête est plus efficace que la requête normal '%john%', parce que la base de données à besoin de vérifier uniquement le début des données de la colonne, plutôt que de parcourir entièrement les données de la colonne. De plus, si la colonne est indéxée, certaines bases de données sont capables d’utiliser l’index pour cette requête, même s’il s’agit d’une requête LIKE. |
| = | correspond exactement, sans tenir compte de la casse. Par exemple, si search_fields vaut ['=first_name', '=last_name'] et qu’un utilisateur recherche john lennon, Django fera l’équivalent de cette clause SQL WHERE: WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john') AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon') Notez que la requête saisie est coupée par des espaces, ainsi, en suivant cet exemple, il n’est actuellement pas possible de chercher toutes les entrées dans lesquelles first_name est exactement 'john winston' (contenant une espace). |
| @ | Correspondance complète du texte. Cela est similaire à la méthode de recherche par défaut, mais en utilisant un index. Actuellement, ceci n’est valable quepour MySQL. |
Dernière modification: 2008-08-04 13:37:58.334922