save many to many data

8 views
Skip to first unread message

Antonio

unread,
Feb 6, 2007, 5:52:45 AM2/6/07
to Django users
Hi all,
I have a class with a many2many field:

class Previsione(models.Model):
nave = models.CharField(maxlength=50)
data_manovra = models.DateField()
h_inizio = models.TimeField()
rims = models.ManyToManyField(Rim)

into the views.py I use this code to save the submitted data:

....
if req.method == 'POST':
myform = nf.models.form_for_model(Previsione)(req.POST)

if myform.is_valid():
dati = myform.save(commit=False)

if varid is not None:
dati.id=varid

dati.save()

dati.rims = req.POST.getlist('rims')

return HttpResponseRedirect('.')
else:
....

but when I update the data the old rims are deleted and the new inserted ... is
possible to UPDATE the rims data ? cioe', is possible to leave unchanged the
rims data if are the same ?

tanks in advance ...

--
#include <stdio.h>
int main(void){char c[]={10,65,110,116,111,110,105,111,32,98,97,114,98,111,110,
101,32,60,104,105,110,100,101,109,105,116,64,116,105,115,99,97,108,105,110,101,
116,46,105,116,62,10,10,0};printf("%s",c);return 0;}

Russell Keith-Magee

unread,
Feb 6, 2007, 7:10:04 AM2/6/07
to django...@googlegroups.com
On 2/6/07, Antonio <stra...@tiscali.it> wrote:

> Hi all,
> I have a class with a many2many field:

...
> but when I update the data the old rims are deleted and the new inserted ... is
> possible to UPDATE the rims data ? cioe', is possible to leave unchanged the
> rims data if are the same ?

data.rims.add(req.POST.getlist('rims'))

should do what you need it to do, assuming what has been posted is a
list of valid primary keys or object instances.

data.rims is a descriptor; it behaves a lot like an attribute (because
it has __get__ and __set__ implementations), but it also has some
helpful utility methods (like add(), remove() and clear()).

Yours,
Russ Magee %-)

Antonio

unread,
Feb 6, 2007, 10:06:16 AM2/6/07
to django...@googlegroups.com
* martedì 06 febbraio 2007, alle 20:10, Russell Keith-Magee wrote :
> data.rims.add(req.POST.getlist('rims'))

*****************
Exception Type: TypeError
Exception Value: list objects are unhashable
*****************

I've try with:

for newrim in req.POST.getlist('rims'):
dati.rims.add(newrim)

but the data are added also when I update the Previsione ...
searching on group archive, I think I must implement a 'save' method
into the Previsione class ... is correct ?

and if it's correct, how can I access the POST data from the save() method ?

> Yours,
> Russ Magee %-)

tanks ...

Antonio

unread,
Feb 6, 2007, 12:07:16 PM2/6/07
to django...@googlegroups.com
* martedì 06 febbraio 2007, alle 20:10, Russell Keith-Magee wrote :

for the moment, I've resolved this way:

if req.method == 'POST':
myform = nf.models.form_for_model(Previsione)(req.POST)

if myform.is_valid():
dati = myform.save(commit=False)

salva_rims = True
list_rims = req.POST.getlist('rims')

if varid is not None:
dati.id=varid

old_rims=list(dati.rims.all())
new_rims=Rim.objects.in_bulk(list_rims).values()
old_rims.sort()
new_rims.sort()

if old_rims == new_rims:
salva_rims = False

dati.save()

if salva_rims == True:
dati.rims = list_rims

return HttpResponseRedirect('.')
else:

any better (and more elegant !! ;-)) idea ??

tanks in advance ....

Russell Keith-Magee

unread,
Feb 6, 2007, 9:27:54 PM2/6/07
to django...@googlegroups.com
On 2/7/07, Antonio <stra...@tiscali.it> wrote:
>
> * martedì 06 febbraio 2007, alle 20:10, Russell Keith-Magee wrote :
> > data.rims.add(req.POST.getlist('rims'))

Oops - sorry - missed a small, but very important bit - You need to
roll out the list as arguments. Ordinarily, the usage of add() would
be:

data.rims.add(1,3,7,9)

but since you already have a list, you use:

data.rims.add(*req.POST.getlist('rims'))

Sorry for leading you astray.

> I've try with:
>
> for newrim in req.POST.getlist('rims'):
> dati.rims.add(newrim)

This is effectively the same solution, but rolled out in code.

> but the data are added also when I update the Previsione ...
> searching on group archive, I think I must implement a 'save' method
> into the Previsione class ... is correct ?

I'm not sure I understand what you're trying to do here. The save()
method on an instance doesn't affect the m2m relations. However, there
are other mechanisms, such as saving a web form, that will modify m2m
forms.

How are you updating the Previsione instances? Using a web form?
Programmatically? Some other way?

> and if it's correct, how can I access the POST data from the save() method ?

In short, you can't. However, this doesn't stop you from adding a
different method to your model that has the side effect of calling
save.

Yours,
Russ Magee %-)

Antonio

unread,
Feb 7, 2007, 4:19:52 AM2/7/07
to django...@googlegroups.com
* mercoledì 07 febbraio 2007, alle 11:27, Russell Keith-Magee wrote :
> > but the data are added also when I update the Previsione ...
> > searching on group archive, I think I must implement a 'save' method
> > into the Previsione class ... is correct ?
>
> I'm not sure I understand what you're trying to do here. The save()
> method on an instance doesn't affect the m2m relations. However, there
> are other mechanisms, such as saving a web form, that will modify m2m
> forms.

what do you mean with "saving a web form" ?? saving the form and NOT
the save method on instance ??

I use :
***
myform = nf.models.form_for_model(Previsione)(req.POST)

if myform.is_valid():
dati = myform.save(commit=False)

***

to change eventually the 'id' value for the insert/update

***


if varid is not None:
dati.id=varid

***

> How are you updating the Previsione instances? Using a web form?
> Programmatically? Some other way?

I create a web form to insert/update the Previsione data ... my urls.py:

urlpatterns = patterns('modulistica.savona.views',
(r'^index/$', 'index'),
(r'^Previsione/$', 'previsione'),
(r'^Previsione/(?P<varid>\d+)/$', 'previsione'),
)

when I get the 'Previsione/' URL I go to insert the data ... when I get
the 'Previsione/10/' URL I go to update the data of the Previsione(pk=10).

****************************
the previsione function :

def previsione(req, varid=None):


if req.method == 'POST':
myform = nf.models.form_for_model(Previsione)(req.POST)

if myform.is_valid():
dati = myform.save(commit=False)

salva_rims = True


list_rims = req.POST.getlist('rims')

if varid is not None:
dati.id=varid
clean_path=re.sub('/[0-9]+/','',req.path)
else:
clean_path = req.path

# controlla se ci sono stati cambiamenti
# nel campo m2m
#
old_rims=list(dati.rims.all())
new_rims=Rim.objects.in_bulk(list_rims).values()
old_rims.sort()
new_rims.sort()

if old_rims == new_rims:
salva_rims = False

dati.save()

if salva_rims == True:
dati.rims = list_rims

return HttpResponseRedirect(clean_path)
else:
# method GET
#
if varid is None:
myform = nf.models.form_for_model(Previsione)()
else:
instance = get_object_or_404(Previsione, pk=varid)
myform = nf.models.form_for_instance(instance)()

return render_to_response('create_form.html', \
{ 'titolo': 'Archivio Previsioni',
'form': myform.as_table() })

tanks for the help ;-))) and sorry for my english !!

Russell Keith-Magee

unread,
Feb 7, 2007, 6:17:36 PM2/7/07
to django...@googlegroups.com
On 2/7/07, Antonio <stra...@tiscali.it> wrote:
>
> * mercoledì 07 febbraio 2007, alle 11:27, Russell Keith-Magee wrote :
> > > but the data are added also when I update the Previsione ...
> > > searching on group archive, I think I must implement a 'save' method
> > > into the Previsione class ... is correct ?
> >
> > I'm not sure I understand what you're trying to do here. The save()
> > method on an instance doesn't affect the m2m relations. However, there
> > are other mechanisms, such as saving a web form, that will modify m2m
> > forms.
>
> what do you mean with "saving a web form" ?? saving the form and NOT
> the save method on instance ??
>
> I use :
> ***
> myform = nf.models.form_for_model(Previsione)(req.POST)
>
> if myform.is_valid():
> dati = myform.save(commit=False)
> ***

Ok - this is saving a form created from a model. Since your model
contains a m2m field, the form representing that model will have an
m2m widget, and when you save() the form, the m2m relation on the
object will be modified.

However, if you had an instance of Previsione, and saved it, the m2m
fields would not be affected:

obj = Previsione(...# some initial data #...)
obj.save() # Does not modify m2m data

What was confusing me was that it sounded like you wanted to override
save() on Previsione (the model), rather than overriding save() on the
Previsione form. The former idea won't help; the latter idea will.

What you describe in your example looks to be correct - rather than
using the save() method on the form for Previsione, you are manually
saving the object modified by the form, which allows you to be
specific about saving m2m relations, etc.

If you were really fancy, you could wrap that logic into a save method
on a custom form; this would make your view a little cleaner, but
wouldn't affect the way the view operates.

Yours,
Russ Magee %-)

Antonio

unread,
Feb 8, 2007, 4:29:22 AM2/8/07
to django...@googlegroups.com
* giovedì 08 febbraio 2007, alle 07:17, Russell Keith-Magee wrote :
> Ok - this is saving a form created from a model. Since your model
> contains a m2m field, the form representing that model will have an
> m2m widget, and when you save() the form, the m2m relation on the
> object will be modified.

ok ... first of all TANKS for the help and for the very clear explanation
;-)))

I've resolved (more clear and more coincise !!) with:

*******


def previsione(req, varid=None):
if req.method == 'POST':

myform = nf.models.form_for_model(Prev)(req.POST)

if myform.is_valid():


if varid is not None:

instance = get_object_or_404(Prev, pk=varid)
newforms.models.save_instance(myform, instance)
else:
myform.save()

clean_path=re.sub('/[0-9]+/','',req.path)

return HttpResponseRedirect(clean_path)
else:
....
********

the last thing is that the m2m data are ALWAYS updated with an increment of
the 'id', even if data are unchanged ... but I think I've to "play"
(eventually ;-))) with the 'save()' method ...

tanks again .... my turn next time ... I hope ;-)))

bye ....

Reply all
Reply to author
Forward
0 new messages