2009/11/4 Georg Göttlich <m...@dvine.de>: > > Hi everybody, > > I have a problem with denormalizing a m2m field. For several reasons I > want to save a CSV string of all the authors of a text. The authors > are manage in an m2m field to auth.user. The changes are made with the > admin. > > First I tried to override the save() method of the model. This didn't > work. Even with first calling save on the parent and doing a fresh > query within the save() function I always get the state of the authors > before the change. After the save operation I have the correct list of > authors in the m2m field but an incorrect serialization in the > denormalized charfield. If I then save again (via the admin interface) > without changing anything it obviously works. > > Next I tried using the post_save signal. Same results. > > Then someone in the channel suggested to override an admin function > and I tried overriding save_model. Same results here as well. > > I don't really know what to do next and I simply don't understand > what's going on. When are these m2m relations updated? Is there > perhaps a seperate signal. Do I somehow need to resync due to internal > caching or something weird like that? > I would be very glad for any suggestions in the toppic! Thanks a lot > in advance.
The problem you are experiencing is caused by a misunderstanding about the handling of m2m fields: m2m saving and model saving are independent processes. The call to set: book.authors = [a,b,c,d] doesn't have any interaction on the Book model itself - it only interacts with the m2m table. As a result, it doesn't invoke the save() method on Book, or issue the pre/post_save signal. When you assign a value to an m2m field, the m2m field is updated *immediately*, without any need to call save() on the parent model. An example: book = Book.objects.filter(...) # retrieve a book from the db book.name = 'asdf' # Set the name - no db activity book.pagecount = 42 # Set the pagecount - no db activity book.authors = [a,b,c,d] # Write the m2m data to the database book.save() # Write the name and pagecount to the database A related issue here is that when you create a new book instance, you can't assign to an m2m field until *after* the instance has been saved for the first time - until the book has been saved, it doesn't have a primary key, so the m2m table has nothing to link to. In your case, ticket #5390 is the fix to your problem. This ticket proposes to introduce a signal on m2m saving. You could then connect your denormalization method to this signal. This ticket has been on the todo list for a while - it narrowly missed inclusion in v1.1. I hope to be able to get this into trunk for v1.2. In the meantime, you will need to use a workaround. The easiest workaround I can think of is to introduce an intermediate model [1]. Django allows you to manually define the model to use to store m2m relations. This was originally intended to allow you to store extra data on the m2m relationship, but there is no requirement that you do this - you can define an intermediate m2m table that just stores the m2m data. By defining your own m2m intermediate table, you get a standalone class, which means you can override the save method on the m2m table. Put your denormalization in that save method, and you're done. The unfortunate side effect of this approach is that you won't be able to do direct assignment of m2m relations (i.e., you won't be able to say book.authors = [a,b,c]). Instead, you will need to manually create instances of the intermediate relation. [1] http://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships Yours, Russ Magee %-) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---