Opened 8 years ago

Closed 8 years ago

#4312 closed (wontfix)

addition of defaults argument to newforms save()

Reported by: ctdecci@… Owned by: adrian
Component: Forms Version: master
Severity: Keywords:
Cc: Triage Stage: Design decision needed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

I'd like the ability to call save() on a form and insert some values for fields (e.g., non-editable or to the instance before it is saved. This way, calling save(False) to return an object which is subsequently manipulated then saved again can be avoided. I'm not sure if 'defaults' is the best name for this argument, but that's what I've implemented for now. For example:

Given these models:

from django.db import models

class Foo(models.Model):
    name = models.CharField(maxlength=16)

class Bar(models.Model):
    name = models.CharField(maxlength=16)
    foo = models.ForeignKey(Foo, editable=False)

Here is the example:

>>> from django import newforms as forms
>>> from mysite.myapp.models import *
>>>
>>> my_foo = Foo(name='My Foo')
>>> my_foo.save()
>>> Form1 = forms.form_for_model(Bar)
>>> form = Form1({ 'name': 'My Bar'})
>>> form.is_valid()
True
>>> form.save(defaults={ 'foo': my_foo })
<Bar: Bar object>
>>> Form2 = forms.form_for_model(Bar, fields=('baz'))
>>> form = Form2({})
>>> form.is_valid()
True
>>> form.save(defaults={ 'name': 'My Bar 2', 'foo': my_foo })
<Bar: Bar object>
>>>                                                                    

Attachments (1)

models.diff (1.8 KB) - added by ctdecci@… 8 years ago.

Download all attachments as: .zip

Change History (4)

Changed 8 years ago by ctdecci@…

comment:1 follow-up: Changed 8 years ago by Simon G. <dev@…>

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Design decision needed

Hmm.. what benefits does this have over using initial values?

comment:2 in reply to: ↑ 1 Changed 8 years ago by anonymous

Replying to Simon G. <dev@simon.net.nz>:

Hmm.. what benefits does this have over using initial values?

I'm not sure that "defaults" was the right terminology for this. This was not intended to provide an initial value for the Form field or a default value for the Model attribute. Instead, this was meant as a "hook" that would allow the developer to supply values for Model attributes that are not intended to be a form field (neither hidden nor visible)--usually fields that are not "editable" or are not included in the "fields" argument to newforms.models.form_for_instance() or newforms.models.form_for_model().

A better example might be something like this:

from django.db import models
from django.contrib.auth.models import User

class Blog(models.Model):
    name = models.CharField(maxlength=16)

class Entry(models.Model):
    blog = models.ForeignKey(Blog, editable=False)
    user = models.ForeignKey(User, editable=False)
    text = models.TextField()

When an Entry is created, the blog and user attributes are required, but they won't be part of the form--they must be supplied by some other means (e.g., the session, URL, or query string). Then they are added to the instance by passing them into the "defaults" argument of the Form's save method. This way save(False) doesn't need to be called before the attributes are set. In this case it's mostly needed when creating the instance. If there is many_to_many data, then that would also have to be handled somehow (see docs for save_instance()).

There may be other ways to do this, but I found this to be backwards compatible and relatively simple solution...

comment:3 Changed 8 years ago by russellm

  • Resolution set to wontfix
  • Status changed from new to closed

This functionality is already provided by the save(False) approach. Attaching data to the form that isn't required for form presentation isn't really a good idea, IMHO.

There is a problem with the save(False) approach when it comes to m2m data. This problem is described in ticket #4001, but that problem is solvable. The solution is to fix #4001, not to make form_for_model a behemoth. Remember, form_for_model is a helper, not the end of the story on newforms.

Note: See TracTickets for help on using tickets.
Back to Top