web-dev-qa-db-fra.com

Django ModelForm: à quoi sert save (commit = False)?

Pourquoi devrais-je jamais utiliser save(commit=False) au lieu de simplement créer un objet de formulaire à partir de la sous-classe ModelForm et d'exécuter is_valid() pour valider à la fois le formulaire et le modèle?

En d'autres termes, à quoi sert save(commit=False)?

Si cela ne vous dérange pas, pourriez-vous fournir des situations hypothétiques où cela pourrait être utile?

67
sgarza62

C'est utile lorsque vous obtenez la plupart de vos données de modèle à partir d'un formulaire, mais que vous devez remplir null=False champs contenant des données autres que des formulaires.

L'enregistrement avec commit = False vous obtient un objet modèle, vous pouvez ensuite ajouter vos données supplémentaires et les enregistrer.

Ceci est un bon exemple de cette situation.

81
dokkaebi

Voici la réponse ( de la documentation ):

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

La situation la plus courante consiste à obtenir l'instance à partir du formulaire, mais uniquement "en mémoire", pas dans la base de données. Avant de l'enregistrer, vous souhaitez apporter des modifications:

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()
31
dani herrera

Depuis les documents Django:

Cette méthode save () accepte un argument de mot clé commit facultatif, qui accepte True ou False. Si vous appelez save () avec commit = False, il renverra un objet qui n'a pas encore été enregistré dans la base de données.

Dans ce cas, c'est à vous d'appeler save () sur l'instance de modèle résultante. Ceci est utile si vous souhaitez effectuer un traitement personnalisé sur l'objet avant de l'enregistrer ou si vous souhaitez utiliser l'une des options d'enregistrement de modèle spécialisées. commit est True par défaut.

Il semble que save (commit = False) crée une instance de modèle, qu'elle vous renvoie. Ce qui est bien pour certains post-traitements avant de les enregistrer!

9
A.J.Rouvoet

En tant que "véritable exemple", considérez un modèle utilisateur où l'adresse e-mail et le nom d'utilisateur sont toujours les mêmes, puis vous pouvez remplacer la méthode de sauvegarde de votre ModelForm comme:

class UserForm(forms.ModelForm):
    ...
    def save(self):
        # Sets username to email before saving
        user = super(UserForm, self).save(commit=False)
        user.username = user.email
        user.save()
        return user

Si vous n'avez pas utilisé commit=False pour définir le nom d'utilisateur sur l'adresse e-mail, vous devez soit modifier la méthode de sauvegarde du modèle utilisateur, soit enregistrer l'objet utilisateur deux fois (ce qui duplique une opération de base de données coûteuse).

8
Mark Chackerian