Что касается form.save(commit=False), что я упускаю?

Как объясняется во многих постах, например, в следующем: Зачем мы используем «form.save(commit=False)» в Django-views? «Основной вариант использования - если у вас есть форма ModelForm, которая не содержит всех необходимых полей модели. Вам нужно сохранить эту форму в базе данных, но поскольку вы не указали все необходимые поля, вы получите ошибку...», что все хорошо и замечательно, но почему бы просто не заполнить все поля экземпляра и затем вызвать обычное сохранение? В приведенном ниже примере:

# Creates a Dog class with all fields as mandatory:
class Dog(models.Model):
    name = models.CharField(max_length=50)
    race = models.CharField(max_length=50)
    age = models.PositiveIntegerField()

# Creates a ModelForm with only name and age:
class DogForm(forms.ModelForm):
    class Meta:
        model = Dog
        fields = ['name', 'age']

# In your view use this form:
def dog_view(request):
    ...
    form = DogForm(request.POST or None)
    # If the form is valid we need to add a race, otherwise we will get an error:
    if form.is_valid():
        dog = form.save(commit=False)
        # Define the race here:
        dog.race = 'Labrador retriever'
        # And then do the regular save to push the change in the database:
        dog.save()
        ...

почему бы просто не сказать:

    form = DogForm(request.POST or None)
        # Define the race:
        dog.race = 'Labrador retriever'
        if form.is_valid():
            # Do the regular save:
            dog.save()

Что я здесь упускаю?

это все хорошо и замечательно, но почему бы просто не заполнить все поля экземпляра, а затем вызвать обычное сохранение?

That is possible. In fact I recommend this approach in an article I wrote [django-antipatterns].

Но я бы посоветовал позволить форме управлять логикой, например:

def dog_view(request):
    # …
    form = DogForm(request.POST, request.FILES)
    if form.is_valid():
        form.instance.race = 'Labrador retriever'
        form.save()
    # …

Основная причина этого в том, что формы Django также могут сохранять многие-ко-многим поля, а значит, делать больше запросов к базе данных. Используя dog.save(), вы сохраняете экземпляр собаки, и в этом случае все в порядке. Но если у вас есть ManyToManyField с именем owners, например. Таким образом, он больше не будет сохранять владельцев собаки.


Note: While most forms do not process media files, it is probably better to pass request.FILES [Django-doc] to the form anyway, such that if you later add an extra media field, all views that use the form will indeed handle the files properly.

Вернуться на верх