Ejemplo n.º 1
0
    def usage_for_model(self,
                        model,
                        counts=False,
                        min_count=None,
                        filters=None,
                        extra=None):
        """
        Obtain a list of tags associated with instances of the given
        Model class.

        If ``counts`` is True, a ``count`` attribute will be added to
        each tag, indicating how many times it has been used against
        the Model class in question.

        If ``min_count`` is given, only tags which have a ``count``
        greater than or equal to ``min_count`` will be returned.
        Passing a value for ``min_count`` implies ``counts=True``.

        To limit the tags (and counts, if specified) returned to those
        used by a subset of the Model's instances, pass a dictionary
        of field lookups to be applied to the given Model as the
        ``filters`` argument.
        """
        if extra is None: extra = {}
        if filters is None: filters = {}

        if not parse_lookup:
            # post-queryset-refactor (hand off to usage_for_queryset)
            queryset = model._default_manager.filter()
            for f in filters.items():
                queryset.query.add_filter(f)
            usage = self.usage_for_queryset(queryset, counts, min_count, extra)
        else:
            # pre-queryset-refactor
            extra_joins = ''
            extra_criteria = ''
            params = []
            if len(filters) > 0:
                joins, where, params = parse_lookup(filters.items(),
                                                    model._meta)
                extra_joins = ' '.join([
                    '%s %s AS %s ON %s' % (join_type, table, alias, condition)
                    for (alias, (table, join_type,
                                 condition)) in joins.items()
                ])
                extra_criteria = 'AND %s' % (' AND '.join(where))
            usage = self._get_usage(model, counts, min_count, extra_joins,
                                    extra_criteria, params, extra)

        return usage
Ejemplo n.º 2
0
    def usage_for_model(self, model, counts=False, min_count=None, filters=None):
        """
        Obtain a list of tags associated with instances of the given
        Model class.

        If ``counts`` is True, a ``count`` attribute will be added to
        each tag, indicating how many times it has been used against
        the Model class in question.

        If ``min_count`` is given, only tags which have a ``count``
        greater than or equal to ``min_count`` will be returned.
        Passing a value for ``min_count`` implies ``counts=True``.

        To limit the tags (and counts, if specified) returned to those
        used by a subset of the Model's instances, pass a dictionary
        of field lookups to be applied to the given Model as the
        ``filters`` argument.
        """
        if filters is None:
            filters = {}

        if not parse_lookup:
            # post-queryset-refactor (hand off to usage_for_queryset)
            queryset = model._default_manager.filter()
            for f in filters.items():
                queryset.query.add_filter(f)
            usage = self.usage_for_queryset(queryset, counts, min_count)
        else:
            # pre-queryset-refactor
            extra_joins = ""
            extra_criteria = ""
            params = []
            if len(filters) > 0:
                joins, where, params = parse_lookup(filters.items(), model._meta)
                extra_joins = " ".join(
                    [
                        "%s %s AS %s ON %s" % (join_type, table, alias, condition)
                        for (alias, (table, join_type, condition)) in joins.items()
                    ]
                )
                extra_criteria = "AND %s" % (" AND ".join(where))
            usage = self._get_usage(model, counts, min_count, extra_joins, extra_criteria, params)

        return usage
Ejemplo n.º 3
0
    def usage_for_model(self,
                        Model,
                        counts=False,
                        min_count=None,
                        filters=None):
        """
        Obtain a list of tags associated with instances of the given
        Model.

        If ``counts`` is True, a ``count`` attribute will be added to
        each tag, indicating how many times it has been used against
        the Model in question.

        If ``min_count`` is given, only tags which have a ``count``
        greater than or equal to ``min_count`` will be returned.
        Passing a value for ``min_count`` implies ``counts=True``.

        To limit the tags (and counts, if specified) returned to those
        used by a subset of the Model's instances, pass a dictionary
        of field lookups to be applied to the given Model as the
        ``filters`` argument.
        """
        if filters is None: filters = {}
        if min_count is not None: counts = True

        model_table = backend.quote_name(Model._meta.db_table)
        model_pk = '%s.%s' % (model_table,
                              backend.quote_name(Model._meta.pk.column))
        query = """
        SELECT DISTINCT %(tag)s.id, %(tag)s.name%(count_sql)s
        FROM
            %(tag)s
            INNER JOIN %(tagged_item)s
                ON %(tag)s.id = %(tagged_item)s.tag_id
            INNER JOIN %(model)s
                ON %(tagged_item)s.object_id = %(model_pk)s
            %%s
        WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
            %%s
        GROUP BY %(tag)s.id, %(tag)s.name
        %%s
        ORDER BY %(tag)s.name ASC""" % {
            'tag':
            backend.quote_name(self.model._meta.db_table),
            'count_sql':
            counts and (', COUNT(%s)' % model_pk) or '',
            'tagged_item':
            backend.quote_name(
                self._get_related_model_by_accessor('items')._meta.db_table),
            'model':
            model_table,
            'model_pk':
            model_pk,
            'content_type_id':
            ContentType.objects.get_for_model(Model).id,
        }

        extra_joins = ''
        extra_criteria = ''
        min_count_sql = ''
        params = []
        if len(filters) > 0:
            joins, where, params = parse_lookup(filters.items(), Model._meta)
            extra_joins = ' '.join([
                '%s %s AS %s ON %s' % (join_type, table, alias, condition)
                for (alias, (table, join_type, condition)) in joins.items()
            ])
            extra_criteria = 'AND %s' % (' AND '.join(where))
        if min_count is not None:
            min_count_sql = 'HAVING COUNT(%s) >= %%s' % model_pk
            params.append(min_count)

        cursor = connection.cursor()
        cursor.execute(query % (extra_joins, extra_criteria, min_count_sql),
                       params)
        tags = []
        for row in cursor.fetchall():
            t = self.model(*row[:2])
            if counts:
                t.count = row[2]
            tags.append(t)
        return tags
Ejemplo n.º 4
0
    def usage_for_model(self, model, counts=False, min_count=None, filters=None):
        """
        Obtain a list of tags associated with instances of the given
        Model class.

        If ``counts`` is True, a ``count`` attribute will be added to
        each tag, indicating how many times it has been used against
        the Model class in question.

        If ``min_count`` is given, only tags which have a ``count``
        greater than or equal to ``min_count`` will be returned.
        Passing a value for ``min_count`` implies ``counts=True``.

        To limit the tags (and counts, if specified) returned to those
        used by a subset of the Model's instances, pass a dictionary
        of field lookups to be applied to the given Model as the
        ``filters`` argument.
        """
        if filters is None: filters = {}
        if min_count is not None: counts = True

        model_table = qn(model._meta.db_table)
        model_pk = '%s.%s' % (model_table, qn(model._meta.pk.column))
        query = """
        SELECT DISTINCT %(tag)s.id, %(tag)s.name%(count_sql)s
        FROM
            %(tag)s
            INNER JOIN %(tagged_item)s
                ON %(tag)s.id = %(tagged_item)s.tag_id
            INNER JOIN %(model)s
                ON %(tagged_item)s.object_id = %(model_pk)s
            %%s
        WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
            %%s
        GROUP BY %(tag)s.id, %(tag)s.name
        %%s
        ORDER BY %(tag)s.name ASC""" % {
            'tag': qn(self.model._meta.db_table),
            'count_sql': counts and (', COUNT(%s)' % model_pk) or '',
            'tagged_item': qn(self._get_related_model_by_accessor('items')._meta.db_table),
            'model': model_table,
            'model_pk': model_pk,
            'content_type_id': ContentType.objects.get_for_model(model).pk,
        }

        extra_joins = ''
        extra_criteria = ''
        min_count_sql = ''
        params = []
        if len(filters) > 0:
            joins, where, params = parse_lookup(filters.items(), model._meta)
            extra_joins = ' '.join(['%s %s AS %s ON %s' % (join_type, table, alias, condition)
                                    for (alias, (table, join_type, condition)) in joins.items()])
            extra_criteria = 'AND %s' % (' AND '.join(where))
        if min_count is not None:
            min_count_sql = 'HAVING COUNT(%s) >= %%s' % model_pk
            params.append(min_count)

        cursor = connection.cursor()
        cursor.execute(query % (extra_joins, extra_criteria, min_count_sql), params)
        tags = []
        for row in cursor.fetchall():
            t = self.model(*row[:2])
            if counts:
                t.count = row[2]
            tags.append(t)
        return tags