Example #1
0
        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'))))
Example #2
0
        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'))))
Example #3
0
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