149👍
That’s useful when you get most of your model data from a form, but you need to populate some null=False
fields with non-form data.
Saving with commit=False
gets you a model object, then you can add your extra data and save it.
This is a good example of that situation.
Here’s the documentation on the save method. Note that if your form includes many-to-many fields, you’ll also want to call form.save_m2m()
after saving the model instance.
53👍
Here it is the answer (from docs):
# 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)
The most common situation is to get the instance from form but only ‘in memory’, not in database. Before save it you want to make some changes:
# Modify the author in some way.
>>> new_author.some_field = 'some_value'
# Save the new instance.
>>> new_author.save()
- [Django]-What is choice_set in this Django app tutorial?
- [Django]-What's the difference between CharField and TextField in Django?
- [Django]-How to make an auto-filled and auto-incrementing field in django admin
24👍
From the Django docs:
This save() method accepts an optional commit keyword argument,
which accepts either True or False. If you call save() withcommit=False
,
then it will return an object that hasn’t yet been saved to the database.In this case, it’s up to you to call save() on the resulting model instance.
This is useful if you want to do custom processing on the object before saving it,
or if you want to use one of the specialized model saving options.
commit is True by default.
It seems that save(commit=False
) does create a model instance, which it returns to you. Which is neat for some post processing before actually saving it!
- [Django]-'staticfiles' is not a valid tag library: Template library staticfiles not found
- [Django]-How to run own daemon processes with Django?
- [Django]-What is a "django backend"?
11👍
As a “real example”, consider a user model where the email address and the username are always the same, and then you could overwrite your ModelForm’s save method like:
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
If you didn’t use commit=False
to set the username to the email address, you’d either have to modify the user model’s save method, or save the user object twice (which duplicates an expensive database operation.)
- [Django]-Django REST framework post array of objects
- [Django]-Is it better to use path() or url() in urls.py for django 2.0?
- [Django]-Add inline model to django admin site
2👍
The basic thing here I understand is that it changes from a ‘form’ instance to a particular ‘model’ instance in view.
Let suppose I want to post an answer like this in StackOverflow.
The code would be like this:
# Create a form instance with POST data.
>>> form_data = AnswerForm(request.POST)
# Create, but don't save the new answer instance.
>>> Answer = form_data.save(commit=False)
So now we have to add the owner of this answer and save this in our database in the view page like this:
>>> Answer.owner = request.user
>>> Answer.save()
So like this, we can add the owner of this answer which we cannot do like form_data.owner = request.user
in the view page and also not in the form class.
So basically, it changes from ‘form’ instance to ‘model’ instance and then lets you to modify the data and save it.
- [Django]-PHP Frameworks (CodeIgniter, Yii, CakePHP) vs. Django
- [Django]-Django Rest Framework custom response message
- [Django]-Referencing multiple submit buttons in django
1👍
form = AddAttachmentForm(request.POST, request.FILES)
if form.is_valid():
attachment = form.save(commit=False)
attachment.user = student
attachment.attacher = self.request.user
attachment.date_attached = timezone.now()
attachment.competency = competency
attachment.filename = request.FILES['attachment'].name
if attachment.filename.lower().endswith(('.png','jpg','jpeg','.ai','.bmp','.gif','.ico','.psd','.svg','.tiff','.tif')):
attachment.file_type = "image"
if attachment.filename.lower().endswith(('.mp4','.mov','.3g2','.avi','.flv','.h264','.m4v','.mpg','.mpeg','.wmv')):
attachment.file_type = "video"
if attachment.filename.lower().endswith(('.aif','.cda','.mid','.midi','.mp3','.mpa','.ogg','.wav','.wma','.wpl')):
attachment.file_type = "audio"
if attachment.filename.lower().endswith(('.csv','.dif','.ods','.xls','.tsv','.dat','.db','.xml','.xlsx','.xlr')):
attachment.file_type = "spreasheet"
if attachment.filename.lower().endswith(('.doc','.pdf','.rtf','.txt')):
attachment.file_type = "text"
attachment.save()
here is my example of using save(commit=False). I wanted to check what type of file a user uploaded before saving it to the database. I also wanted to get the date it was attached since that field was not in the form.
- [Django]-What is the equivalent of "none" in django templates?
- [Django]-Django – how to visualize signals and save overrides?
- [Django]-Whats the difference between using {{STATIC_URL}} and {% static %}
1👍
In simple words, here we update the form object and let them know that don’t save the values in the database right now, we might change some input with instance and then use .save() to save all values in the database.
This gives us the flexibility to get all values from the HTML form and customize them according to our requirement and then save the instance.
- [Django]-How to run own daemon processes with Django?
- [Django]-What is more efficient .objects.filter().exists() or get() wrapped on a try
- [Django]-Custom django admin templates not working
0👍
-
save(commit=False) cannot save objects but can return objects in a list and is used to customize the submitted inline objects in Django Admin. *As far as I researched and experimented, using
save(commit=False)
is the easiest way to customize the submitted inline objects in Django Admin. -
save()
equivalent tosave(commit=True)
can save objects, then can retrun objects in a list and is not used to customize the submitted inline objects in Django Admin because more queries are run.
For example, there are Category
model and Product
model which has the foreign key of Category
model as shown below:
# "my_app/models.py"
class Category(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class Product(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=20)
def __str__(self):
return self.name
And, there is overridden save_formset() with print(formset.save())
in Category
admin which has Product
inline as shown below. *save_formset()
is run when changing inline objects:
# "my_app/admin.py"
class ProductInline(admin.TabularInline):
model = Product
extra = 0
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
inlines = (ProductInline,)
def save_formset(self, request, form, formset, change):
print(formset.save()) # Here
And, there is Fruits
category which has Apple
and Orange
products as shown below:
Now, I change Apple
to Apple Juice
and Orange
to Orange Juice
by clicking on SAVE as shown below:
Then, Apple
is changed to Apple Juice
and Orange
is changed to Orange Juice
as shown below:
Then, 2 inline objects are returned in a list on console as shown below:
[<Product: Apple Juice>, <Product: Orange Juice>]
And, two inline objects are saved by two UPDATE
queries according to the PostgreSQL logs below. *You can see my answer explaining about how to log queries in PostgreSQL:
Next, I use formset.save(commit=False)
as shown below:
# "my_app/admin.py"
# ...
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
inlines = (ProductInline,)
def save_formset(self, request, form, formset, change):
print(formset.save(commit=False)) # Here
Now again, I change Apple
to Apple Juice
and Orange
to Orange Juice
by clicking on SAVE as shown below:
Then, Apple
is not changed to Apple Juice
and Orange
is not changed to Orange Juice
as shown below:
Then, 2 inline objects are returned in a list on console as shown below:
[<Product: Apple Juice>, <Product: Orange Juice>]
Then, two inline objects are not saved by two UPDATE
queries according to the PostgreSQL logs below:
Next, I make the submitted names of inline objects uppercase with formset.save(commit=False)
as shown below. *Again, save(commit=False)
is used to customize the submitted inline objects in Django Admin:
# "my_app/admin.py"
# ...
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
inlines = (ProductInline,)
def save_formset(self, request, form, formset, change):
for object in formset.save(commit=False): # Here
object.name = object.name.upper()
formset.save()
Now, I add Vegetable
category, Cucumber
and Potato
products by clicking on SAVE as shown below:
Then, Cucumber
and Potato
are made uppercase as shown below:
And, two inline objects are saved by two INSERT
queries according to the PostgreSQL logs below:
Next, I make the submitted names of inline objects uppercase with formset.save()
as shown below. *Again, save()
equivalent to save(commit=True)
is not used to customize the submitted inline objects in Django Admin because more queries are run:
# "my_app/admin.py"
# ...
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
inlines = (ProductInline,)
def save_formset(self, request, form, formset, change):
for object in formset.save(): # Here
object.name = object.name.upper()
formset.save()
Now again, I add Vegetable
category, Cucumber
and Potato
products by clicking on SAVE as shown below:
Then again, Cucumber
and Potato
are made uppercase as shown below:
And first, two inline objects with Cucumber
and Potato
are saved by two INSERT
, and second, two inline objects with CUCUMBER
and POTATO
are saved by two UPDATE
queries according to the PostgreSQL logs below:
So, don’t use save()
to customize the submitted inline objects in Django Admin because more queries are run. Instead, you should use save(commit=False)
to customize the submitted inline objects in Django Admin.
- [Django]-How do I convert a Django QuerySet into list of dicts?
- [Django]-Django – How to rename a model field using South?
- [Django]-Django Rest Framework remove csrf