﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
905	[patch] Add _pre_set and _post_set hooks to models	andreas@…	Adrian Holovaty	"""set_thingie"" methods for many-to-many related objects (as well as ""set_thingie_order"" and ""get_thingie_order"" methods) don't trigger _pre_save or _post_save. I needed these hooks so here's a small patch that adds them.

{{{
Index: django/core/meta/__init__.py
===================================================================
--- /home/andreas/workspace/django_src/django/core/meta/__init__.py	(revision 1396)
+++ /home/andreas/workspace/django_src/django/core/meta/__init__.py	(working copy)
@@ -924,6 +960,9 @@
 # Handles setting many-to-many relationships.
 # Example: Poll.set_sites()
 def method_set_many_to_many(rel_field, self, id_list):
+    # Run any pre-set hooks.
+    if hasattr(self, '_pre_set'):
+        self._pre_set()
     current_ids = [obj.id for obj in method_get_many_to_many(rel_field, self)]
     ids_to_add, ids_to_delete = dict([(i, 1) for i in id_list]), []
     for current_id in current_ids:
@@ -956,6 +995,9 @@
         delattr(self, '_%s_cache' % rel_field.name) # clear cache, if it exists
     except AttributeError:
         pass
+    # Run any post-set hooks.
+    if hasattr(self, '_post_set'):
+        self._post_set()
     return True
 
 # Handles related-object retrieval.
@@ -990,6 +1032,9 @@
 # Handles setting many-to-many related objects.
 # Example: Album.set_songs()
 def method_set_related_many_to_many(rel_opts, rel_field, self, id_list):
+    # Run any pre-set hooks.
+    if hasattr(self, '_pre_set'):
+        self._pre_set()
     id_list = map(int, id_list) # normalize to integers
     rel = rel_field.rel.to
     m2m_table = rel_field.get_m2m_db_table(rel_opts)
@@ -1004,6 +1049,9 @@
         db.db.quote_name(rel_opts.object_name.lower() + '_id'))
     cursor.executemany(sql, [(this_id, i) for i in id_list])
     db.db.commit()
+    # Run any post-set hooks.
+    if hasattr(self, '_post_set'):
+        self._post_set()
 
 # ORDERING METHODS #########################
 
@@ -1008,6 +1056,9 @@
 # ORDERING METHODS #########################
 
 def method_set_order(ordered_obj, self, id_list):
+    # Run any pre-set hooks.
+    if hasattr(self, '_pre_set'):
+        self._pre_set()
     cursor = db.db.cursor()
     # Example: ""UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s""
     sql = ""UPDATE %s SET %s = %%s WHERE %s = %%s AND %s = %%s"" % \
@@ -1017,6 +1068,9 @@
     rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name)
     cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)])
     db.db.commit()
+    # Run any pre-set hooks.
+    if hasattr(self, '_post_set'):
+        self._pre_set()
 
 def method_get_order(ordered_obj, self):
     cursor = db.db.cursor()
}}}

The patch is probably not universally useful since you might want to further differentiate between set_order and set_many_to_many."	enhancement	closed	Core (Other)		normal	wontfix			Unreviewed	1	0	0	0	0	0
