def test_uses_backend_specific_quoting(self): """Backend-specific quotes should be used Table and field names should be quoted with the quote_name function provided by the database backend. The test here is a bit trivial since a real-life test case with PostgreSQL schema tricks or other table/field name munging would be difficult. """ qn = db.connection.ops.quote_name qs = _select_related_instances(Entry, 'id', [1], 'batch_select_entry', 'section_id') sql = qs.query.as_sql()[0] self.failUnless(sql.startswith('SELECT (%s.%s) AS ' %( qn('batch_select_entry'), qn('section_id'))))
def test_uses_backend_specific_quoting(self): """Backend-specific quotes should be used Table and field names should be quoted with the quote_name function provided by the database backend. The test here is a bit trivial since a real-life test case with PostgreSQL schema tricks or other table/field name munging would be difficult. """ qn = db.connection.ops.quote_name qs = _select_related_instances(Entry, 'section', [1], 'batch_select_entry', 'section_id') db.reset_queries() list(qs) sql = db.connection.queries[-1]['sql'] self.failUnless( sql.startswith('SELECT (%s.%s) AS ' % (qn('batch_select_entry'), qn('section_id'))))
def batch_select(model, instances, target_field_name, fieldname, filter=None): ''' basically do an extra-query to select the many-to-many field values into the instances given. e.g. so we can get all Entries and their Tags in two queries rather than n+1 returns a list of the instances with the newly attached fields batch_select(Entry, Entry.objects.all(), 'tags_all', 'tags') would return a list of Entry objects with 'tags_all' fields containing the tags for that Entry filter is a function that can be used alter the extra-query - it takes a queryset and returns a filtered version of the queryset NB: this is a semi-private API at the moment, but may be useful if you dont want to change your model/manager. ''' fieldname = _check_field_exists(model, fieldname) instances = list(instances) ids = [instance.pk for instance in instances] field_object, model, direct, m2m = model._meta.get_field_by_name(fieldname) if m2m: if not direct: m2m_field = field_object.field related_model = field_object.model related_name = m2m_field.name id_column = m2m_field.m2m_reverse_name() db_table = m2m_field.m2m_db_table() else: m2m_field = field_object related_model = m2m_field.rel.to # model on other end of relationship related_name = m2m_field.related_query_name() id_column = m2m_field.m2m_column_name() db_table = m2m_field.m2m_db_table() elif not direct: # handle reverse foreign key relationships fk_field = field_object.field related_model = field_object.model related_name = fk_field.name id_column = fk_field.column db_table = related_model._meta.db_table related_instances = _select_related_instances(related_model, related_name, ids, db_table, id_column) if filter: related_instances = filter(related_instances) grouped = {} id_attr = _id_attr(id_column) for related_instance in related_instances: instance_id = getattr(related_instance, id_attr) group = grouped.get(instance_id, []) group.append(related_instance) grouped[instance_id] = group for instance in instances: setattr(instance, target_field_name, grouped.get(instance.pk, [])) return instances