def _create_batch(self, batch_or_str, target_field_name=None): batch = batch_or_str if isinstance(batch_or_str, basestring): batch = Batch(batch_or_str) if target_field_name: batch.target_field_name = target_field_name _check_field_exists(self.model, batch.m2m_fieldname) return batch
def test___check_field_exists_full_field_name(self): # make sure we can retrieve the "real" fieldname # given the full fieldname for a reverse foreign key # relationship # e.g. give "entry_set" we should get "entry" self.failUnlessEqual("entry", _check_field_exists(Section, "entry_set"))
def _check_field_exists(model, fieldname): try: field_object, model, direct, m2m = model._meta.get_field_by_name( fieldname) except FieldDoesNotExist: # might be after reverse foreign key # which by default don't have the name we expect if fieldname.endswith('_set'): return _check_field_exists(model, fieldname[:-len('_set')]) else: raise if not m2m: if direct: # reverse foreign key relationship _not_exists(fieldname) return fieldname
def test___check_field_exists_full_field_name_non_existant_field(self): try: _check_field_exists(Section, "qwerty_set") self.fail('selected field that does not exist') except FieldDoesNotExist: pass
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