---
title: "Référence des instances de modèles"
version: 2.2
locale: fr
source: https://docs.djangoproject.com/fr/2.2/ref/models/instances/
canonical: https://djangodocs.dev/fr/2.2/ref/models/instances/
---
# Référence des instances de modèles

Ce document détaille l’API des objets `Model`. Il augmente les contenus présentés dans les guides des [modèles](/fr/2.2/topics/db/models/) et des [requêtes de base de données](/fr/2.2/topics/db/queries/), il est donc conseillé de lire et de comprendre ces derniers avant de lire celui-ci.

Tout au long de cette référence, nous utiliserons les [modèles d’exemple Weblog](/fr/2.2/topics/db/queries/#queryset-model-example) présentés dans le [guide des requêtes de base de données](/fr/2.2/topics/db/queries/).

## Création d’objets

Pour créer une nouvelle instance d’un modèle, il suffit de l’instancier comme n’importe quelle autre classe Python :

#### `class Model(**kwargs)`

Les paramètres nommés sont simplement les noms des champs définis dans le modèle. Notez que l’instanciation d’un modèle ne touche pas à la base de données ; pour cela, il faut enregistrer avec [`save()`](#django.db.models.Model.save).

> **Note**
>
> Vous pourriez être tenté de personnaliser le modèle en surchargeant sa méthode `__init__`. Cependant, si vous faites cela, prenez soin de ne pas modifier la signature de la méthode car tout changement pourrait bloquer l’enregistrement de l’instance de modèle. Plutôt que de surcharger `__init__`, essayer d’utiliser l’une de ces approches :
>
> 1. Ajouter une méthode `classmethod` sur la classe du modèle :
>
>    ```
>    from django.db import models
>
>    class Book(models.Model):
>        title = models.CharField(max_length=100)
>
>        @classmethod
>        def create(cls, title):
>            book = cls(title=title)
>            # do something with the book
>            return book
>
>    book = Book.create("Pride and Prejudice")
>    ```
> 2. Ajouter une méthode dans un gestionnaire personnalisé (souvent plus judicieux) :
>
>    ```
>    class BookManager(models.Manager):
>        def create_book(self, title):
>            book = self.create(title=title)
>            # do something with the book
>            return book
>
>    class Book(models.Model):
>        title = models.CharField(max_length=100)
>
>        objects = BookManager()
>
>    book = Book.objects.create_book("Pride and Prejudice")
>    ```

### Personnalisation du chargement des modèles

#### `classmethod Model.from_db(db, field_names, values)`

La méthode `from_db()` peut être utilisée pour personnaliser la création des instances de modèles lors de leur chargement à partir de la base de données.

Le paramètre `db` contient l’alias de la base de données à partir de laquelle le modèle est chargé, `field_names` contient les noms de tous les champs chargés et `values` contient les valeurs chargées pour chaque champ de `field_names`. L’ordre des champs dans `field_names` est le même que dans `values`. Si tous les champs du modèle sont présents, `values` est toujours dans l’ordre attendu par `__init__()`. Cela signifie que l’instance peut être créée par `cls(*values)`. Si certains champs sont différés, ils n’apparaissent pas dans `field_names`. Dans ce cas, attribuez une valeur `django.db.models.DEFERRED` à chacun des champs manquants.

En plus de créer le nouveau modèle, la méthode `from_db()` doit définir les drapeaux `adding` et `db` de l’attribut `_state` de la nouvelle instance.

Dans l’exemple ci-dessous, on voit comment mémoriser les valeurs des champs telles que chargées à partir de la base de données :

```
from django.db.models import DEFERRED

@classmethod
def from_db(cls, db, field_names, values):
    # Default implementation of from_db() (subject to change and could
    # be replaced with super()).
    if len(values) != len(cls._meta.concrete_fields):
        values = list(values)
        values.reverse()
        values = [
            values.pop() if f.attname in field_names else DEFERRED
            for f in cls._meta.concrete_fields
        ]
    instance = cls(*values)
    instance._state.adding = False
    instance._state.db = db
    # customization to store the original field values on the instance
    instance._loaded_values = dict(zip(field_names, values))
    return instance

def save(self, *args, **kwargs):
    # Check how the current values differ from ._loaded_values. For example,
    # prevent changing the creator_id of the model. (This example doesn't
    # support cases where 'creator_id' is deferred).
    if not self._state.adding and (
            self.creator_id != self._loaded_values['creator_id']):
        raise ValueError("Updating the value of creator isn't allowed")
    super().save(*args, **kwargs)
```

L’exemple ci-dessus montre une implémentation complète de `from_db()` pour clarifier son fonctionnement. Dans ce cas, il aurait bien sûr été possible de simplement faire appel à `super()` dans la méthode `from_db()`.

## Actualisation des objets à partir de la base de données

Si vous supprimez un champ à partir d’une instance de modèle, un nouvel accès va recharger la valeur de la base de données :

```
>>> obj = MyModel.objects.first()
>>> del obj.field
>>> obj.field  # Loads the field from the database
```

#### `Model.refresh_from_db(using=None, fields=None)`

Si vous avez besoin de recharger les valeurs d’un modèle à partir de la base de données, vous pouvez utiliser la méthode `refresh_from_db()`. Lorsque cette méthode est appelée sans paramètre, voici ce qui se passe :

1. Tous les champs non différés du modèle sont mis à jour avec les valeurs actuellement présentes en base de données.
2. Toutes les relations en cache sont effacées de l’instance rechargée.

Seuls les champs du modèle sont rechargés à partir de la base de données. D’autres valeurs dépendantes de la base de données telles que les annotations ne sont pas rechargées. Tout attribut [`@cached_property`](/fr/2.2/ref/utils/#django.utils.functional.cached_property) n’est pas non plus réinitialisé.

Le rechargement s’opère à partir de la base de données à l’origine des valeurs existantes, ou de la base de données par défaut si l’instance n’a pas été chargée à partir de la base de données. Le paramètre `using` peut être utilisé pour forcer la base de données source du rechargement.

Il est possible de forcer le groupe de champs à recharger en utilisant le paramètre `fields`.

Par exemple, pour tester qu’un appel à `update()` a effectivement produit le résultat attendu, vous pourriez écrire un test semblable à celui-ci :

```
def test_update_result(self):
    obj = MyModel.objects.create(val=1)
    MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
    # At this point obj.val is still 1, but the value in the database
    # was updated to 2. The object's updated value needs to be reloaded
    # from the database.
    obj.refresh_from_db()
    self.assertEqual(obj.val, 2)
```

Notez que quand on accède à des champs différés, le chargement de la valeur différée du champ s’effectue avec cette méthode. Il est donc possible de personnaliser la manière de charger les données différées. L’exemple ci-dessous montre comment l’on peut recharger tous les champs d’une instance lorsqu’un champ différé est rechargé :

```
class ExampleModel(models.Model):
    def refresh_from_db(self, using=None, fields=None, **kwargs):
        # fields contains the name of the deferred field to be
        # loaded.
        if fields is not None:
            fields = set(fields)
            deferred_fields = self.get_deferred_fields()
            # If any deferred field is going to be loaded
            if fields.intersection(deferred_fields):
                # then load all of them
                fields = fields.union(deferred_fields)
        super().refresh_from_db(using, fields, **kwargs)
```

#### `Model.get_deferred_fields()`

Une méthode utilitaire renvoyant un ensemble contenant les noms d’attributs de tous les champs d’un modèle qui sont actuellement différés.

## Validation d’objets

La validation d’un modèle se déroule en trois étapes :

1. Validation des champs de modèle - [`Model.clean_fields()`](#django.db.models.Model.clean_fields)
2. Validation du modèle en entier - [`Model.clean()`](#django.db.models.Model.clean)
3. Validation de l’unicité des champs - [`Model.validate_unique()`](#django.db.models.Model.validate_unique)

Les trois étapes sont effectuées lorsque la méthode [`full_clean()`](#django.db.models.Model.full_clean) d’un modèle est appelée.

Lors de l’utilisation d’un formulaire [`ModelForm`](/fr/2.2/topics/forms/modelforms/#django.forms.ModelForm), l’appel à [`is_valid()`](/fr/2.2/ref/forms/api/#django.forms.Form.is_valid) effectue ces étapes de validation pour tous les champs inclus dans le formulaire. Consultez la [documentation de ModelForm](/fr/2.2/topics/forms/modelforms/) pour plus d’informations. L’appel à la méthode [`full_clean()`](#django.db.models.Model.full_clean) d’un modèle ne devrait être nécessaire que lorsque l’on souhaite s’occuper soi-même des erreurs de validation ou si des champs ont été exclu du [`ModelForm`](/fr/2.2/topics/forms/modelforms/#django.forms.ModelForm) et qu’ils nécessitent une validation.

#### `Model.full_clean(exclude=None, validate_unique=True)`

Cette méthode appelle [`Model.clean_fields()`](#django.db.models.Model.clean_fields), [`Model.clean()`](#django.db.models.Model.clean) et [`Model.validate_unique()`](#django.db.models.Model.validate_unique) (si `validate_unique` vaut `True`), dans cet ordre et peut générer une exception  [`ValidationError`](/fr/2.2/ref/exceptions/#django.core.exceptions.ValidationError) avec un attribut `message_dict` contenant les erreurs produites par les trois méthodes.

Le paramètre facultatif `exclude` peut être utilisé pour fournir une liste de noms de champs qui peuvent être exclus de la validation et du nettoyage. [`ModelForm`](/fr/2.2/topics/forms/modelforms/#django.forms.ModelForm) utilise ce paramètre pour exclure de la validation les champs qui sont absents du formulaire, car d’éventuelles erreurs ne pourraient pas être corrigées par l’utilisateur.

Notez que `full_clean()` ne sera *pas* appelée automatiquement lorsque vous appelez la méthode [`save()`](#django.db.models.Model.save) d’un modèle. Il faut l’appeler manuellement au moment où vous souhaitez effectuer la validation de modèle pour vos propres modèles. Par exemple :

```
from django.core.exceptions import ValidationError
try:
    article.full_clean()
except ValidationError as e:
    # Do something based on the errors contained in e.message_dict.
    # Display them to a user, or handle them programmatically.
    pass
```

La première chose que fait `full_clean()` est de procéder au nettoyage de chaque champ individuellement.

#### `Model.clean_fields(exclude=None)`

Cette méthode valide tous les champs du modèle. Le paramètre facultatif `exclude` peut être utilisé pour fournir une liste de noms de champs à exclure de la validation. Une exception [`ValidationError`](/fr/2.2/ref/exceptions/#django.core.exceptions.ValidationError) est générée pour chaque champ dont la validation échoue.

La deuxième chose que fait `full_clean()` est d’appeler [`Model.clean()`](#django.db.models.Model.clean). Cette méthode peut être surchargée pour effectuer une validation personnalisée du modèle.

#### `Model.clean()`

C’est cette méthode qui devrait être utilisée pour fournir une validation de modèle personnalisée et pour modifier des attributs du modèle, le cas échéant. Par exemple, on pourrait profiter de cette méthode pour attribuer une valeur automatique à un champ ou pour procéder à une validation qui nécessite de pouvoir accéder à d’autres champs du modèle :

```
import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError(_('Draft entries may not have a publication date.'))
        # Set the pub_date for published items if it hasn't been set already.
        if self.status == 'published' and self.pub_date is None:
            self.pub_date = datetime.date.today()
```

Notez cependant que comme pour [`Model.full_clean()`](#django.db.models.Model.full_clean), la méthode `clean()` d’un modèle n’est pas invoquée lors d’un appel à la méthode [`save()`](#django.db.models.Model.save) du modèle.

Dans l’exemple ci-dessus, l’exception [`ValidationError`](/fr/2.2/ref/exceptions/#django.core.exceptions.ValidationError) générée par `Model.clean()` a été créée en lui passant une chaîne, elle sera donc stockée dans une clé particulière d’un dictionnaire d’erreurs, [`NON_FIELD_ERRORS`](/fr/2.2/ref/exceptions/#django.core.exceptions.NON_FIELD_ERRORS). Cette clé est réservée aux erreurs liées au modèle dans son entier plutôt qu’à un champ spécifique :

```
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
try:
    article.full_clean()
except ValidationError as e:
    non_field_errors = e.message_dict[NON_FIELD_ERRORS]
```

Pour attribuer une exception à un champ particulier, créez une instance de [`ValidationError`](/fr/2.2/ref/exceptions/#django.core.exceptions.ValidationError) avec un dictionnaire dont les clés correspondent aux noms de champs. Nous pourrions mettre à jour l’exemple précédent en attribuant l’erreur au champ `pub_date`:

```
class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})
        ...
```

Si vous détectez des erreurs dans plusieurs champs pendant `Model.clean()`, il est aussi possible de passer un dictionnaire faisant correspondre des noms de champs aux erreurs :

```
raise ValidationError({
    'title': ValidationError(_('Missing title.'), code='required'),
    'pub_date': ValidationError(_('Invalid date.'), code='invalid'),
})
```

Finalement, `full_clean()` vérifie les contraintes d’unicité éventuelles du modèle.

> **Comment générer des erreurs de validation spécifiques à certains champs si ceux-ci n’apparaissent pas dans un ModelForm**
>
> Il n’est pas possible de générer des erreurs de validation dans `Model.clean()` pour des champs qui n’apparaissent pas dans un formulaire de modèle (un formulaire peut limiter ses champs à l’aide des attributs `Meta.fields` ou `Meta.exclude`). Si vous essayez, vous obtiendrez une exception `ValueError` car l’erreur de validation ne pourra pas être associée au champ absent du formulaire.
>
> Pour contourner ce problème, il est possible de surcharger [`Model.clean_fields()`](#django.db.models.Model.clean_fields) car elle reçoit la liste des champs qui sont exclus de la validation. Par exemple
>
> ```
> class Article(models.Model):
>     ...
>     def clean_fields(self, exclude=None):
>         super().clean_fields(exclude=exclude)
>         if self.status == 'draft' and self.pub_date is not None:
>             if exclude and 'status' in exclude:
>                 raise ValidationError(
>                     _('Draft entries may not have a publication date.')
>                 )
>             else:
>                 raise ValidationError({
>                     'status': _(
>                         'Set status to draft if there is not a '
>                         'publication date.'
>                      ),
>                 })
> ```

#### `Model.validate_unique(exclude=None)`

Cette méthode est semblable à [`clean_fields()`](#django.db.models.Model.clean_fields), mais elle valide toutes les contraintes d’unicité du modèle au lieu des valeurs de champs individuelles. Le paramètre facultatif `exclude` peut être utilisé pour fournir une liste de noms de champs à exclure de la validation. Une exception [`ValidationError`](/fr/2.2/ref/exceptions/#django.core.exceptions.ValidationError) est générée pour chaque champ dont la validation échoue.

Notez que si vous renseignez le paramètre `exclude` de `validate_unique()`, les contraintes [`unique_together`](/fr/2.2/ref/models/options/#django.db.models.Options.unique_together) impliquant l’un des champs de la liste ne seront pas contrôlées.

## Enregistrement d’objets

Pour enregistrer un objet dans la base de données, appelez `save()`:

#### `Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)`

Si vous souhaitez personnaliser le comportement d’enregistrement, vous pouvez surcharger cette méthode `save()`. Voir [Surcharge des méthodes de modèles prédéfinies](/fr/2.2/topics/db/models/#overriding-model-methods) pour plus de détails.

Le processus d’enregistrement des modèles comporte également certaines subtilités ; voir les sections ci-dessous.

### Incrémentation automatique des clés primaires

Si un modèle contient un champ [`AutoField`](/fr/2.2/ref/models/fields/#django.db.models.AutoField) – une clé primaire avec incrémentation automatique – la valeur incrémentée automatiquement sera calculée et enregistrée comme attribut de l’objet lors de son premier enregistrement avec `save()`:

```
>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id     # Returns None, because b2 doesn't have an ID yet.
>>> b2.save()
>>> b2.id     # Returns the ID of your new object.
```

Il n’est pas possible de connaître la valeur future de l’identifiant avant d’appeler `save()`, car cette valeur est calculée par la base de données, et non par Django.

Par commodité, chaque modèle possède par défaut un champ [`AutoField`](/fr/2.2/ref/models/fields/#django.db.models.AutoField) nommé `id`, sauf dans le cas où vous ajoutez explicitement le paramètre `primary_key=True` à l’un des champs du modèle. Consultez la documentation de [`AutoField`](/fr/2.2/ref/models/fields/#django.db.models.AutoField) pour plus de détails.

#### La propriété `pk`

#### `Model.pk`

Que vous définissiez vous-même un champ de clé primaire ou que vous laissiez Django s’en charger, chaque modèle possède une propriété nommée `pk`. Elle se comporte comme un attribut normal du modèle, mais représente en réalité un alias vers l’attribut du modèle qui a la fonction de clé primaire. Vous pouvez lire et définir cette valeur, comme vous le feriez pour tout autre attribut, et l’action s’applique au bon champ du modèle, c’est-à-dire à la clé primaire.

#### Définition explicite des valeurs de clés primaires

Si un modèle contient un champ [`AutoField`](/fr/2.2/ref/models/fields/#django.db.models.AutoField) mais que vous souhaiteriez définir explicitement l’identifiant d’un nouvel objet lors de son enregistrement, il suffit de le faire juste avant de l’enregistrer, plutôt que de compter sur l’attribution automatique de l’identifiant :

```
>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b3.id     # Returns 3.
>>> b3.save()
>>> b3.id     # Returns 3.
```

Si vous attribuez manuellement des valeurs de clé primaire habituellement automatiques, prenez garde de ne pas utiliser des valeurs déjà existantes ! Si vous créez un nouvel objet avec une valeur de clé primaire explicite qui existe déjà dans la base de données, Django pense que vous modifiez un objet existant, et non que vous en créez un nouveau.

En reprenant l’exemple du blog `'Cheddar Talk'` ci-dessus, cet exemple écraserait l’objet existant dans la base de données :

```
b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save()  # Overrides the previous blog with ID=3!
```

Lisez [Comment Django distingue UPDATE de INSERT](#how-django-knows-to-update-vs-insert) ci-dessous, pour comprendre pourquoi cela se passe ainsi.

La définition explicite de valeurs de clés primaires est essentiellement utile lors de l’enregistrement d’objets en vrac, lorsque l’on est à peu près certain qu’il n’y aura pas de collision de clés primaires.

Si vous utilisez PostgreSQL, la séquence associée à la clé primaire pourrait devoir être mise à jour ; voir [Indication manuelle des valeurs de clé primaire avec autoincrémentation](/fr/2.2/ref/databases/#manually-specified-autoincrement-pk).

### Que se passe-t-il lors de l’enregistrement ?

Lorsque vous enregistrez un objet, Django effectue les étapes suivantes :

1. **Émission d’un signal avant enregistrement.** Le signal [`django.db.models.signals.pre_save`](/fr/2.2/ref/signals/#django.db.models.signals.pre_save) est envoyé, permettant à toute fonction à l’écoute de ce signal d’accomplir une action.
2. **Préparation des données.** La méthode [`pre_save()`](/fr/2.2/ref/models/fields/#django.db.models.Field.pre_save) de chaque champ est appelée pour effectuer toute éventuelle modification automatique de données. Par exemple, les champs date/heure surchargent `pre_save()` pour implémenter [`auto_now_add`](/fr/2.2/ref/models/fields/#django.db.models.DateField.auto_now_add) et [`auto_now`](/fr/2.2/ref/models/fields/#django.db.models.DateField.auto_now).
3. **Préparation des données pour la base de données.** La méthode [`get_db_prep_save()`](/fr/2.2/ref/models/fields/#django.db.models.Field.get_db_prep_save) de chaque champ doit fournir sa valeur actuelle dans un type de données qui peut être écrit dans la base de données.

   La plupart des champs ne nécessitent aucune préparation de données. Les types de données simples, comme les entiers ou les chaînes de caractères, sont « prêtes à l’écriture » en tant qu’objet Python. Cependant, les types de données plus complexes ont souvent besoin de certaines modifications.

   Par exemple, les champs [`DateField`](/fr/2.2/ref/models/fields/#django.db.models.DateField) utilisent un objet Python `datetime` pour stocker leurs données. Les bases de données ne peuvent pas stocker d’objet `datetime`, il faut donc que la valeur du champ soit convertie dans une chaîne date au format ISO pour être insérée dans la base de données.
4. **Insertion des données dans la base de données.** Les données pré-traitées et préparées sont converties en instruction SQL en vue de leur insertion dans la base de données.
5. **Émission d’un signal après enregistrement.** Le signal [`django.db.models.signals.post_save`](/fr/2.2/ref/signals/#django.db.models.signals.post_save) est envoyé, permettant à toute fonction à l’écoute de ce signal d’accomplir une action.

### Comment Django distingue UPDATE de INSERT

Vous avez peut-être remarqué que les objets de base de données de Django utilisent la même méthode `save()` pour créer ou modifier des objets. La couche d’abstraction de Django évite de devoir différencier les instructions SQL `INSERT` ou `UPDATE`. Plus concrètement, lors de l’appel à `save()`, Django suit l’algorithme suivant :

- Si l’attribut de clé primaire de l’objet est défini à une valeur équivalent à `True` (c’est-à-dire une valeur autre que `None` ou que la chaîne vide), Django effectue une instruction `UPDATE` (mise à jour).
- Si l’attribut de clé primaire de l’objet n’est *pas* défini où si l’instruction `UPDATE` n’a rien mis à jour (par ex. si la clé primaire est définie à une valeur qui n’existe pas en base de données), Django exécute une requête `INSERT`.

Le point délicat ici est de faire attention à ne pas indiquer explicitement de valeur de clé primaire lors de l’enregistrement de nouveaux objets, si vous ne pouvez garantir que cette clé primaire est libre. Pour plus de détails sur cette nuance, consultez [Définition explicite des valeurs de clés primaires](#explicitly-specifying-auto-primary-key-values) ci-dessus et [Contrainte d’insertion ou de mise à jour](#forcing-an-insert-or-update) ci-dessous.

Jusqu’à Django 1.5, Django faisait un `SELECT` lorsque l’attribut de clé primaire était défini. Si le `SELECT` trouvait un objet, Django effectuait ensuite un `UPDATE`, sinon il procédait à un `INSERT`. Cet ancien algorithme produisait une requête supplémentaire dans le cas `UPDATE`. Il peut arriver dans certains cas que la base de données ne signale pas qu’une ligne a été mise à jour même quand il existe une ligne de base de données correspondant à la clé primaire de l’objet. Un exemple est le déclencheur `ON UPDATE` de PostgreSQL qui renvoie `NULL`. Dans de tels cas, il est possible de revenir à l’algorithme précédent en définissant l’option [`select_on_save`](/fr/2.2/ref/models/options/#django.db.models.Options.select_on_save) à `True`.

#### Contrainte d’insertion ou de mise à jour

Dans de rares circonstances, il est nécessaire de pouvoir forcer la méthode [`save()`](#django.db.models.Model.save) à recourir à une instruction SQL `INSERT` au lieu d’une instruction `UPDATE`. Ou l’inverse : mettre à jour si possible, mais ne pas insérer un nouvel enregistrement. Dans ces situations, il est possible de fournir les paramètres `force_insert=True` ou `force_update=True` à la méthode [`save()`](#django.db.models.Model.save). Il est évidemment faux de fournir les deux paramètres simultanément : il est impossible d’insérer *et* de mettre à jour en même temps !

L’usage de ces paramètres est très rare. Django effectue presque toujours le bon choix et en surchargeant le comportement habituel, des erreurs difficiles à détecter peuvent survenir. Cette fonctionnalité est réservée aux experts.

L’utilisation de `update_fields` force une mise à jour de la même façon que `force_update`.

### Mise à jour d’attributs basés sur des champs existants

Il est parfois nécessaire d’effectuer une tâche arithmétique simple sur un champ, comme l’incrémentation ou la décrémentation de la valeur actuelle. La façon évidente de le faire peut ressembler à quelque chose comme :

```
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold += 1
>>> product.save()
```

Si la valeur `number_sold` existante dans la base de données est 10, c’est la valeur 11 qui sera écrite comme nouvelle valeur en base de données.

Ce processus peut être solidifié, [évitant un conflit de concurrence](/fr/2.2/ref/models/expressions/#avoiding-race-conditions-using-f), et rendu légèrement plus rapide en exprimant la mise à jour relativement à la valeur existante plutôt qu’en attribuant explicitement une nouvelle valeur. Django fournit des [`expressions F`](/fr/2.2/ref/models/expressions/#django.db.models.F) pour parvenir à ce genre de mise à jour relative. En employant des [`expressions F`](/fr/2.2/ref/models/expressions/#django.db.models.F), l’exemple précédent est formulé ainsi :

```
>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()
```

Pour plus de détails, consultez la documentation sur les [`expressions F`](/fr/2.2/ref/models/expressions/#django.db.models.F) et leur [emploi dans les requêtes de mise à jour](/fr/2.2/topics/db/queries/#topics-db-queries-update).

### Indication des champs à enregistrer

En transmettant une liste de noms de champs dans le paramètre `update_fields` de `save()`, seuls les champs figurant dans cette liste sont mis à jour. Cela peut être judicieux lorsque un petit sous-ensemble des champs d’un objet doivent être mis à jour. Un léger gain de performances peut être espéré en évitant de mettre à jour tous les champs du modèle en base de données. Par exemple :

```
product.name = 'Name changed again'
product.save(update_fields=['name'])
```

Le paramètre `update_fields` peut être n’importe quel objet itérable contenant des chaînes de caractères. Si ce dernier est vide, l’enregistrement n’a pas lieu. La valeur `None` provoque la mise à jour de tous les champs.

L’utilisation de `update_fields` force une mise à jour.

Lors de l’enregistrement d’un modèle obtenu par chargement différé de modèle ([`only()`](/fr/2.2/ref/models/querysets/#django.db.models.query.QuerySet.only) ou [`defer()`](/fr/2.2/ref/models/querysets/#django.db.models.query.QuerySet.defer)), seuls les champs chargés à partir de la base de données sont mis à jour. Dans ce cas, l’effet est semblable à un `update_fields` automatique. Si vous attribuez ou que vous modifiez l’une des valeurs de champ différé, le champ est ajouté aux champs à mettre à jour.

## Suppression d’objets

#### `Model.delete(using=DEFAULT_DB_ALIAS, keep_parents=False)`

Effectue une instruction SQL `DELETE` pour l’objet. Cela ne fait que supprimer l’objet dans la base de données ; l’instance Python existe toujours et ses champs contiennent encore les données. Cette méthode renvoie le nombre d’objets supprimés ainsi qu’un dictionnaire avec le nombre de suppressions par type d’objet.

Pour plus de détails, y compris sur la suppression d’objets en vrac, consultez [Suppression d’objets](/fr/2.2/topics/db/queries/#topics-db-queries-delete).

Si vous avez besoin d’un comportement de suppression personnalisé, vous pouvez surcharger la méthode `delete()`. Voir [Surcharge des méthodes de modèles prédéfinies](/fr/2.2/topics/db/models/#overriding-model-methods) pour plus de détails.

Il peut arriver parfois qu’avec l”[héritage multi-table](/fr/2.2/topics/db/models/#multi-table-inheritance), on ne veuille supprimer que les données d’un modèle enfant. En indiquant `keep_parents=True`, les données du modèle parent sont conservées.

## Sérialisation « pickle » d’objets

Lorsqu’on utilise [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle) sur un modèle, son état actuel est sérialisé. Lors de la désérialisation, il contiendra l’instance de modèle telle qu’elle était au moment de sa sérialisation, et non pas dans l’état actuel des données de la base de données.

> **Il  n’est pas possible de partager des sérialisations « pickle » entre différentes versions**
>
> Des sérialisations « pickle » de modèles ne sont valables que pour la version de Django utilisée pour les générer. Si vous produisez du contenu « pickle » avec une version N de Django, il n’y a aucune garantie que ce contenu soit lisible par une version N+1 de Django. La sérialisation « pickle » ne doit pas être utilisée dans le cadre d’une stratégie d’archivage à long terme.
>
> Comme des erreurs de compatibilité de pickle peuvent être difficiles à diagnostiquer, comme par exemple des objets silencieusement corrompus, un avertissement `RuntimeWarning` est produit si vous essayer de désérialiser un modèle dans une version de Django différente de celle qui a été utilisée pour la sérialisation.

## Autres méthodes d’instance de modèle

Quelques méthodes d’objet ont un rôle spécifique.

### `__str__()`

#### `Model.__str__()`

La méthode `__str__()` est appelée chaque fois que `str()` est appelée sur un objet. Django utilise `str(obj)` à plusieurs occasions. Plus particulièrement, pour afficher un objet dans le site d’administration de Django et pour produire la valeur insérée dans un gabarit lors de l’affichage d’un objet. Il est donc important de toujours renvoyer une représentation utile et intelligible du modèle en réponse à la méthode `__str__()`.

Par exemple :

```
from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def __str__(self):
        return '%s %s' % (self.first_name, self.last_name)
```

### `__eq__()`

#### `Model.__eq__()`

La méthode d’égalité est définie telle que des instances avec la même valeur de clé primaire et la même classe concrète sont considérées comme égales, sauf pour les instances dont la valeur de clé primaire est `None` qui ne sont toujours égales qu’à elles-mêmes. Pour les modèles mandataires, la classe concrète est définie comme le premier parent non mandataire du modèle ; pour tous les autres modèles, c’est simplement la classe du modèle.

Par exemple :

```
from django.db import models

class MyModel(models.Model):
    id = models.AutoField(primary_key=True)

class MyProxyModel(MyModel):
    class Meta:
        proxy = True

class MultitableInherited(MyModel):
    pass

# Primary keys compared
MyModel(id=1) == MyModel(id=1)
MyModel(id=1) != MyModel(id=2)
# Primary keys are None
MyModel(id=None) != MyModel(id=None)
# Same instance
instance = MyModel(id=None)
instance == instance
# Proxy model
MyModel(id=1) == MyProxyModel(id=1)
# Multi-table inheritance
MyModel(id=1) != MultitableInherited(id=1)
```

### `__hash__()`

#### `Model.__hash__()`

La méthode `__hash__` est basée sur la valeur de clé primaire de l’instance. Il s’agit en pratique de `hash(obj.pk)`. Si l’instance ne possède pas de valeur de clé primaire, une exception `TypeError` est générée (sinon la méthode `__hash__()` renverrait une valeur différente avant et après l’enregistrement de l’instance, alors que la modification de la valeur [`__hash__()`](https://docs.python.org/3/reference/datamodel.html#object.__hash__) d’une instance est interdit en Python).

### `get_absolute_url()`

#### `Model.get_absolute_url()`

Définissez une méthode `get_absolute_url()` pour indiquer à Django la façon de calculer l’URL canonique d’un objet. Pour l’appelant, cette méthode doit renvoyer une chaîne pouvant être utilisée pour se référer à un objet par HTTP.

Par exemple :

```
def get_absolute_url(self):
    return "/people/%i/" % self.id
```

Bien que ce code soit correct et simple, ce n’est peut-être pas la manière la plus portable d’écrire ce genre de méthode. La fonction [`reverse()`](/fr/2.2/ref/urlresolvers/#django.urls.reverse) est habituellement la meilleure approche.

Par exemple :

```
def get_absolute_url(self):
    from django.urls import reverse
    return reverse('people.views.details', args=[str(self.id)])
```

Un endroit où Django utilise `get_absolute_url()` est l’application d’administration. Si un objet définit cette méthode, la page d’édition d’objet présentera un lien « Voir sur le site » qui vous amène directement sur la page d’affichage public de l’objet, telle qu’indiquée par `get_absolute_url()`.

De même, certaines autres parties de Django, comme le [système de flux de syndication](/fr/2.2/ref/contrib/syndication/), utilisent `get_absolute_url()` lorsqu’elle est définie. Si le fait de posséder une URL unique pour chaque instance de modèle fait sens, vous devriez définir `get_absolute_url()`.

> **Warning**
>
> Vous devriez éviter de construire des URL à partir de contenu utilisateur non validé, afin de réduire les possibilités de corruption de lien ou de redirection :
>
> ```
> def get_absolute_url(self):
>     return '/%s/' % self.name
> ```
>
> Si `self.name` est `'/example.com'`, ceci renvoie `'//example.com/'` qui est aussi un protocole valide d’URL relative, mais ne correspond pas à `'/%2Fexample.com/'` qui était attendu.

L’utilisation de `get_absolute_url()` dans les gabarits est reconnu comme une bonne pratique, au lieu de figer les URL des objets à des chaînes fixes. Par exemple, ce code de gabarit est mauvais :

```html+django
<!-- BAD template code. Avoid! -->
<a href="/people/{{ object.id }}/">{{ object.name }}</a>
```

Ce code de gabarit est bien meilleur :

```html+django
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
```

Ici, la logique est que si vous modifiez la structure des URL de vos objets, même s’il ne s’agissait que d’une simple correction orthographique, il n’est pas acceptable de devoir rechercher tous les endroits où l’URL en question pourrait être écrite. On la définit une seule fois dans `get_absolute_url()` et tous les autres endroits du code peuvent alors référencer cette méthode.

> **Note**
>
> La chaîne renvoyée par `get_absolute_url()` ne **doit** contenir que des caractères ASCII (exigence de la spécification d’URI [**RFC 2396 Section 2**](https://datatracker.ietf.org/doc/html/rfc2396.html#section-2)) et être codée en syntaxe URL, si nécessaire.
>
> Le code et les gabarits faisant appel à `get_absolute_url()` doivent pouvoir utiliser le résultat directement sans plus de traitement. Il peut être utile d’appeler la fonction `django.utils.encoding.iri_to_uri()` pour contribuer à cet objectif si vous utilisez des caractères en dehors de la plage ASCII.

## Méthodes d’instances supplémentaires

En plus de [`save()`](#django.db.models.Model.save) et [`delete()`](#django.db.models.Model.delete), un objet de modèle peut posséder certaines des méthodes suivantes :

#### `Model.get_FOO_display()`

Pour chaque champ ayant le paramètre [`choices`](/fr/2.2/ref/models/fields/#django.db.models.Field.choices), l’objet dispose d’une méthode `get_FOO_display()`, où `FOO` est le nom du champ. Cette méthode renvoie une valeur « intelligible » pour ce champ.

Par exemple :

```
from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)
```

```
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
```

#### `Model.get_next_by_FOO(\**kwargs)`

#### `Model.get_previous_by_FOO(\**kwargs)`

Pour chaque champ [`DateField`](/fr/2.2/ref/models/fields/#django.db.models.DateField) et [`DateTimeField`](/fr/2.2/ref/models/fields/#django.db.models.DateTimeField) ne possédant pas le paramètre [`null=True`](/fr/2.2/ref/models/fields/#django.db.models.Field.null), l’objet disposera de méthodes `get_next_by_FOO()` et `get_previous_by_FOO()`, où `FOO` est le nom du champ. Celles-ci renvoient respectivement l’objet suivant et l’objet précédent en fonction du champ date, générant une exception [`DoesNotExist`](#django.db.models.Model.DoesNotExist) le cas échéant.

Ces deux méthodes effectuent leurs requêtes en utilisant le gestionnaire par défaut du modèle. Si vous avez besoin d’émuler le filtrage d’un gestionnaire personnalisé ou que vous vouliez effectuer un filtrage personnalisé unique, ces deux méthodes acceptent aussi des paramètres nommés facultatifs qui devraient correspondre au format décrit dans [Recherches dans les champs](/fr/2.2/ref/models/querysets/#field-lookups).

Notez qu’en cas de valeurs datées identiques, ces méthodes emploient la clé primaire pour déterminer l’objet choisi. Cela permet de garantir qu’aucun objet ne sera omis ou dupliqué. Cela signifie également qu’il n’est pas possible d’utiliser ces méthodes pour des objets non enregistrés.

## Autres attributs

### `DoesNotExist`

#### `exception Model.DoesNotExist`

Cette exception est produite par l’ORM à plusieurs endroits, par exemple par [`QuerySet.get()`](/fr/2.2/ref/models/querysets/#django.db.models.query.QuerySet.get) lorsqu’un objet n’a pas été trouvé en accord avec les paramètres de requête indiqués.

Django fournit une exception `DoesNotExist` comme attribut de chaque classe de modèle afin d’identifier la classe d’objet qui n’a pas pu être trouvé et pour permettre d’intercepter une classe de modèle particulière avec `try/except`. Cette exception est une sous-classe de [`django.core.exceptions.ObjectDoesNotExist`](/fr/2.2/ref/exceptions/#django.core.exceptions.ObjectDoesNotExist).
