Esempio n. 1
0
def _get_content(instance_or_content):
    """
    Given a model instance or a sequence *(content_type, object_id)*
    return a tuple *(content_type, object_id)*.
    """
    try:
        object_id = instance_or_content.pk
    except AttributeError:
        return instance_or_content
    else:
        return (managers.get_content_type_for_model(type(instance_or_content)), object_id)
Esempio n. 2
0
def _get_content(instance_or_content):
    """
    Given a model instance or a sequence *(content_type, object_id)*
    return a tuple *(content_type, object_id)*.
    """
    try:
        object_id = instance_or_content.pk
    except AttributeError:
        return instance_or_content
    else:
        return (managers.get_content_type_for_model(type(instance_or_content)),
                object_id)
Esempio n. 3
0
def annotate_votes(queryset_or_model, key, user, score='score'):
    """
    Annotate *queryset_or_model* with votes, in order to retreive from
    the database all vote values in bulk.
    
    The first argument *queryset_or_model* must be, of course, a queryset
    or a Django model object. The argument *key* is the score key.
    
    The votes are filtered using given *user*. For anonymous voters this
    functionality is unavailable.
    
    The score itself will be present in the attribute named *score* of 
    each instance of the returned queryset.
    
    Usage example::
    
        for article in annotate_votes(Article.objects.all(), 'main', myuser, 
            score='myscore'):
            print 'your vote:', article.myscore    
    """
    # getting the queryset
    if isinstance(queryset_or_model, models.base.ModelBase):
        queryset = queryset_or_model.objects.all()
    else:
        queryset = queryset_or_model
    # preparing arguments for *extra* query
    opts = queryset.model._meta
    content_type = managers.get_content_type_for_model(queryset.model)
    mapping = {
        'vote_table': Vote._meta.db_table,
        'model_table': opts.db_table,
        'model_pk_name': opts.pk.name,
        'content_type_id': content_type.pk,
    }
    # building base query
    template = """
    SELECT score FROM ${vote_table} WHERE 
    ${vote_table}.object_id = ${model_table}.${model_pk_name} AND 
    ${vote_table}.content_type_id = ${content_type_id} AND
    ${vote_table}.user_id = %s AND
    ${vote_table}.key = %s
    """
    select = {score: string.Template(template).substitute(mapping)}
    return queryset.extra(select=select, select_params=[user.pk, key])
Esempio n. 4
0
def annotate_votes(queryset_or_model, key, user, score='score'):
    """
    Annotate *queryset_or_model* with votes, in order to retreive from
    the database all vote values in bulk.
    
    The first argument *queryset_or_model* must be, of course, a queryset
    or a Django model object. The argument *key* is the score key.
    
    The votes are filtered using given *user*. For anonymous voters this
    functionality is unavailable.
    
    The score itself will be present in the attribute named *score* of 
    each instance of the returned queryset.
    
    Usage example::
    
        for article in annotate_votes(Article.objects.all(), 'main', myuser, 
            score='myscore'):
            print 'your vote:', article.myscore    
    """
    # getting the queryset
    if isinstance(queryset_or_model, models.base.ModelBase):
        queryset = queryset_or_model.objects.all()
    else:
        queryset = queryset_or_model
    # preparing arguments for *extra* query
    opts = queryset.model._meta
    content_type = managers.get_content_type_for_model(queryset.model)
    mapping = {
        'vote_table': Vote._meta.db_table,
        'model_table': opts.db_table,
        'model_pk_name': opts.pk.name,
        'content_type_id': content_type.pk,
    }
    # building base query
    template = """
    SELECT score FROM ${vote_table} WHERE 
    ${vote_table}.object_id = ${model_table}.${model_pk_name} AND 
    ${vote_table}.content_type_id = ${content_type_id} AND
    ${vote_table}.user_id = %s AND
    ${vote_table}.key = %s
    """
    select = {score: string.Template(template).substitute(mapping)}
    return queryset.extra(select=select, select_params=[user.pk, key])
Esempio n. 5
0
def annotate_scores(queryset_or_model, key, **kwargs):
    """
    Annotate *queryset_or_model* with scores, in order to retreive from
    the database all score values in bulk.

    The first argument *queryset_or_model* must be, of course, a queryset
    or a Django model object. The argument *key* is the score key.
    
    In *kwargs* it is possible to specify the values to retreive mapped 
    to field names (it is up to you to avoid name clashes).
    You can annotate the queryset with the number of votes (*num_votes*), 
    the average score (*average*) and the total sum of all votes (*total*).
    
    For example, the following call::
    
        annotate_scores(Article.objects.all(), 'main',
            average='average', num_votes='num_votes')
        
    Will return a queryset of article and each article will have two new
    attached fields *average* and *num_votes*.
    
    Of course it is possible to sort the queryset by a score value, e.g.::
    
        for article in annotate_scores(Article, 'by_staff', 
            staff_avg='average', staff_num_votes='num_votes'
            ).order_by('-staff_avg', '-staff_num_votes'):
            print 'staff num votes:', article.staff_num_votes
            print 'staff average:', article.staff_avg
    """
    # getting the queryset
    if isinstance(queryset_or_model, models.base.ModelBase):
        queryset = queryset_or_model.objects.all()
    else:
        queryset = queryset_or_model
    # annotations are done only if fields are requested
    if kwargs:
        # preparing arguments for *extra* query
        select = SortedDict() # not really needed (see below)
        select_params = []
        opts = queryset.model._meta
        content_type = managers.get_content_type_for_model(queryset.model)
        mapping = {
            'score_table': Score._meta.db_table,
            'model_table': opts.db_table,
            'model_pk_name': opts.pk.name,
            'content_type_id': content_type.pk,
        }
        # building base query
        template = """
        SELECT ${field_name} FROM ${score_table} WHERE 
        ${score_table}.object_id = ${model_table}.${model_pk_name} AND 
        ${score_table}.content_type_id = ${content_type_id} AND
        ${score_table}.key = %s
        """
        template = string.Template(template).safe_substitute(mapping)
        # building one query for each requested field
        for alias, field_name in kwargs.items():
            query = string.Template(template).substitute(
                {'field_name': field_name})
            select[alias] = query
            # and that's why SortedDict are not really needed
            select_params.append(key) 
        return queryset.extra(select=select, select_params=select_params)
    return queryset
Esempio n. 6
0
def annotate_scores(queryset_or_model, key, **kwargs):
    """
    Annotate *queryset_or_model* with scores, in order to retreive from
    the database all score values in bulk.

    The first argument *queryset_or_model* must be, of course, a queryset
    or a Django model object. The argument *key* is the score key.
    
    In *kwargs* it is possible to specify the values to retreive mapped 
    to field names (it is up to you to avoid name clashes).
    You can annotate the queryset with the number of votes (*num_votes*), 
    the average score (*average*) and the total sum of all votes (*total*).
    
    For example, the following call::
    
        annotate_scores(Article.objects.all(), 'main',
            average='average', num_votes='num_votes')
        
    Will return a queryset of article and each article will have two new
    attached fields *average* and *num_votes*.
    
    Of course it is possible to sort the queryset by a score value, e.g.::
    
        for article in annotate_scores(Article, 'by_staff', 
            staff_avg='average', staff_num_votes='num_votes'
            ).order_by('-staff_avg', '-staff_num_votes'):
            print 'staff num votes:', article.staff_num_votes
            print 'staff average:', article.staff_avg
    """
    # getting the queryset
    if isinstance(queryset_or_model, models.base.ModelBase):
        queryset = queryset_or_model.objects.all()
    else:
        queryset = queryset_or_model
    # annotations are done only if fields are requested
    if kwargs:
        # preparing arguments for *extra* query
        select = SortedDict()  # not really needed (see below)
        select_params = []
        opts = queryset.model._meta
        content_type = managers.get_content_type_for_model(queryset.model)
        mapping = {
            'score_table': Score._meta.db_table,
            'model_table': opts.db_table,
            'model_pk_name': opts.pk.name,
            'content_type_id': content_type.pk,
        }
        # building base query
        template = """
        SELECT ${field_name} FROM ${score_table} WHERE 
        ${score_table}.object_id = ${model_table}.${model_pk_name} AND 
        ${score_table}.content_type_id = ${content_type_id} AND
        ${score_table}.key = %s
        """
        template = string.Template(template).safe_substitute(mapping)
        # building one query for each requested field
        for alias, field_name in kwargs.items():
            query = string.Template(template).substitute(
                {'field_name': field_name})
            select[alias] = query
            # and that's why SortedDict are not really needed
            select_params.append(key)
        return queryset.extra(select=select, select_params=select_params)
    return queryset