You are right.
Quote from https://doc.openerp.com/6.0/developer/2_5_Objects_Fields_Methods/field_type/#store-parameter:
store Parameter
It will calculate the field and store the result in the table. The field will be recalculated when certain fields are changed on other objects. It uses the following syntax:
store = { 'object_name': ( function_name, ['field_name1', 'field_name2'], priority) }
It will call function function_name when any changes are written to fields in the list ['field1','field2'] on object 'object_name'. The function should have the following signature:
def function_name(self, cr, uid, ids, context=None):
Where ids will be the ids of records in the other object's table that have changed values in the watched fields. The function should return a list of ids of records in its own table that should have the field recalculated. That list will be sent as a parameter for the main function of the field.
So change your store value to (something like):
store = {'student.courses': (_get_student_ids, ['student_ids'], 20)}
and write a function like:
def _get_student_ids(self, cr, uid, ids, context=None):
ids = [];
for course in self.pool.get('student.courses).browse(cr, uid, ids, context=context):
ids.append([student.id for student in course.student_ids]);
return ids;
EDIT:
If your student-course-relationship is bidirectional, you can write a lambda function like:
lambda self,cr,uid,ids,c={}: self.search(cr, uid, [('course_ids','in',ids)])
Regards.