コード例 #1
0
    def get_related_objects(instances, filters=None):
        queryset = None
        apply_filters = mk_filter_function(filters)

        # functioning defining a relationship
        if type(rel_obj_descriptor) in (types.FunctionType, types.MethodType):
            return rel_obj_descriptor(instances, apply_filters)

        # FK from instance to a related object
        elif type(rel_obj_descriptor) == ReverseSingleRelatedObjectDescriptor:
            field = rel_obj_descriptor.field

            rel_obj_attr = field.get_foreign_related_value
            instance_attr = field.get_local_related_value
            query = {'%s__in' % field.related_query_name(): instances}
            rel_mgr = field.rel.to._default_manager
            # If the related manager indicates that it should be used for related
            # fields, respect that.
            if getattr(rel_mgr, 'use_for_related_fields', False):
                queryset = rel_mgr
            else:
                queryset = QuerySet(field.rel.to)
            queryset = queryset.filter(**query).only('pk')

            table = instances[0]._meta.db_table
            pk_field = instances[0]._meta.pk.column
            related_table = field.related_field.model._meta.db_table
            if table == related_table:
                # XXX hack: assuming django uses T2 for joining two tables of same name
                table = 'T2'
            queryset = queryset.extra(
                select={INPUT_ATTR_PREFIX: '%s.%s' % (table, pk_field)})

        # reverse FK from instance to related objects with FK to the instance
        elif type(rel_obj_descriptor) == ForeignRelatedObjectsDescriptor:
            rel_field = rel_obj_descriptor.related.field
            rel_obj_attr = rel_field.get_local_related_value
            rel_column = rel_field.column

            rel_model = rel_obj_descriptor.related.model
            rel_mgr = rel_model._default_manager.__class__()
            rel_mgr.model = rel_model

            query = {'%s__in' % rel_field.name: instances}
            queryset = rel_mgr.get_queryset().filter(**query).only('pk')
            queryset = queryset.extra(
                select={INPUT_ATTR_PREFIX: '%s' % rel_column})

        # M2M from instance to related objects
        elif type(rel_obj_descriptor) in (ReverseManyRelatedObjectsDescriptor,
                                          ManyRelatedObjectsDescriptor):
            db = router.db_for_read(instance.__class__, instance=instance)
            connection = connections[db]

            mgr = rel_obj_descriptor.__get__(instance)
            query = {'%s__in' % mgr.query_field_name: instances}
            queryset = super(mgr.__class__,
                             mgr).get_queryset().filter(**query).only('pk')

            fk = mgr.through._meta.get_field(mgr.source_field_name)
            join_table = mgr.through._meta.db_table
            qn = connection.ops.quote_name
            queryset = queryset.extra(select=dict(
                ('%s%s' % (INPUT_ATTR_PREFIX, f.attname),
                 '%s.%s' % (qn(join_table), qn(f.column)))
                for f in fk.local_related_fields))

        # if you just do 'if queryset', that triggers query execution because
        # python checks length of the enumerable. to prevent query execution, check
        # if queryset is not None.
        if queryset is not None:
            return apply_filters(queryset)

        return []
コード例 #2
0
ファイル: graph.py プロジェクト: benjiec/curious
  def get_related_objects(instances, filters=None):
    queryset = None
    apply_filters = mk_filter_function(filters)

    # functioning defining a relationship
    if type(rel_obj_descriptor) in (types.FunctionType, types.MethodType):
      return rel_obj_descriptor(instances, apply_filters)

    # FK from instance to a related object
    elif type(rel_obj_descriptor) in (ForwardManyToOneDescriptor, ForwardOneToOneDescriptor):
      field = rel_obj_descriptor.field

      rel_obj_attr = field.get_foreign_related_value
      instance_attr = field.get_local_related_value
      query = {'%s__in' % field.related_query_name(): instances}
      rel_mgr = field.rel.to._default_manager
      # If the related manager indicates that it should be used for related
      # fields, respect that.
      if getattr(rel_mgr, 'use_for_related_fields', False):
        queryset = rel_mgr
      else:
        queryset = QuerySet(field.rel.to)
      queryset = queryset.filter(**query).only('pk')

      table = instances[0]._meta.db_table
      pk_field = instances[0]._meta.pk.column
      related_table = field.rel.model._meta.db_table
      if table == related_table:
        # XXX hack: assuming django uses T2 for joining two tables of same name
        table = 'T2'
      queryset = queryset.extra(select={INPUT_ATTR_PREFIX: '%s.%s' % (table, pk_field)})

    # reverse FK from instance to related objects with FK to the instance
    elif type(rel_obj_descriptor) in (ReverseManyToOneDescriptor, ReverseOneToOneDescriptor):
      rel_obj = rel_obj_descriptor.related if (type(rel_obj_descriptor) == ReverseOneToOneDescriptor) else \
        rel_obj_descriptor.rel

      rel_field = rel_obj.field
      rel_obj_attr = rel_field.get_local_related_value
      rel_column = rel_field.column

      rel_model = rel_obj.related_model
      rel_mgr = rel_model._default_manager.__class__()
      rel_mgr.model = rel_model

      query = {'%s__in' % rel_field.name: instances}
      queryset = rel_mgr.get_queryset().filter(**query).only('pk')
      queryset = queryset.extra(select={INPUT_ATTR_PREFIX: '%s' % rel_column})

    # M2M from instance to related objects
    elif type(rel_obj_descriptor) in (ReverseManyToOneDescriptor, ManyToManyDescriptor):
      db = router.db_for_read(instance.__class__, instance=instance)
      connection = connections[db]

      mgr = rel_obj_descriptor.__get__(instance)
      query = {'%s__in' % mgr.query_field_name: instances}
      queryset = super(mgr.__class__, mgr).get_queryset().filter(**query).only('pk')

      fk = mgr.through._meta.get_field(mgr.source_field_name)
      join_table = mgr.through._meta.db_table
      qn = connection.ops.quote_name
      queryset = queryset.extra(select=dict(
        ('%s%s' % (INPUT_ATTR_PREFIX, f.attname),
         '%s.%s' % (qn(join_table), qn(f.column))) for f in fk.local_related_fields))

    # if you just do 'if queryset', that triggers query execution because
    # python checks length of the enumerable. to prevent query execution, check
    # if queryset is not None.
    if queryset is not None:
      return apply_filters(queryset)

    return []