<s> import hashlib <EOL> import django <EOL> from django . contrib . auth . models import User <EOL> from django . contrib . contenttypes . models import ContentType <EOL> from django . contrib . contenttypes . generic import GenericForeignKey <EOL> from django . db import models <EOL> from django . db . models . query import QuerySet <EOL> from ratings . utils import get_content_object_field , is_gfk , recommended_items <EOL> from generic_aggregation import generic_annotate <EOL> class RatedItemBase ( models . Model ) : <EOL> score = models . FloatField ( default = <NUM_LIT:0> , db_index = True ) <EOL> user = models . ForeignKey ( User , related_name = '<STR_LIT>' ) <EOL> hashed = models . CharField ( max_length = <NUM_LIT> , editable = False , db_index = True ) <EOL> class Meta : <EOL> abstract = True <EOL> def __unicode__ ( self ) : <EOL> return u"<STR_LIT>" % ( self . content_object , self . score , <EOL> self . user ) <EOL> def save ( self , * args , ** kwargs ) : <EOL> self . hashed = self . generate_hash ( ) <EOL> super ( RatedItemBase , self ) . save ( * args , ** kwargs ) <EOL> def generate_hash ( self ) : <EOL> content_field = get_content_object_field ( self ) <EOL> related_object = getattr ( self , content_field . name ) <EOL> uniq = '<STR_LIT>' % ( related_object . _meta , related_object . pk ) <EOL> return hashlib . sha1 ( uniq ) . hexdigest ( ) <EOL> @ classmethod <EOL> def lookup_kwargs ( cls , instance ) : <EOL> return { '<STR_LIT>' : instance } <EOL> @ classmethod <EOL> def base_kwargs ( cls , model_class ) : <EOL> return { } <EOL> class RatedItem ( RatedItemBase ) : <EOL> object_id = models . IntegerField ( ) <EOL> content_type = models . ForeignKey ( ContentType , related_name = "<STR_LIT>" ) <EOL> content_object = GenericForeignKey ( ) <EOL> @ classmethod <EOL> def lookup_kwargs ( cls , instance ) : <EOL> return { <EOL> '<STR_LIT>' : instance . pk , <EOL> '<STR_LIT>' : ContentType . objects . get_for_model ( instance ) <EOL> } <EOL> @ classmethod <EOL> def base_kwargs ( cls , model_class ) : <EOL> return { '<STR_LIT>' : ContentType . objects . get_for_model ( model_class ) } <EOL> class Ratings ( object ) : <EOL> def __init__ ( self , rating_model = None ) : <EOL> self . rating_model = rating_model or RatedItem <EOL> def contribute_to_class ( self , cls , name ) : <EOL> setattr ( cls , name , _RatingsDescriptor ( cls , self . rating_model , name ) ) <EOL> setattr ( cls , '<STR_LIT>' , name ) <EOL> class RatingsQuerySet ( QuerySet ) : <EOL> def __init__ ( self , model = None , query = None , using = None , hints = None , <EOL> rated_model = None ) : <EOL> self . rated_model = rated_model <EOL> if django . VERSION < ( <NUM_LIT:1> , <NUM_LIT:7> ) : <EOL> super ( RatingsQuerySet , self ) . __init__ ( model , query , using ) <EOL> else : <EOL> super ( RatingsQuerySet , self ) . __init__ ( model , query , using , hints ) <EOL> def _clone ( self , * args , ** kwargs ) : <EOL> instance = super ( RatingsQuerySet , self ) . _clone ( * args , ** kwargs ) <EOL> instance . rated_model = self . rated_model <EOL> return instance <EOL> def order_by_rating ( self , aggregator = models . Sum , descending = True , <EOL> queryset = None , alias = '<STR_LIT>' ) : <EOL> related_field = get_content_object_field ( self . model ) <EOL> if queryset is None : <EOL> queryset = self . rated_model . _default_manager . all ( ) <EOL> ordering = descending and '<STR_LIT>' % alias or alias <EOL> if not is_gfk ( related_field ) : <EOL> query_name = related_field . related_query_name ( ) <EOL> if len ( self . query . where . children ) : <EOL> queryset = queryset . filter ( ** { <EOL> '<STR_LIT>' % query_name : self . values_list ( '<STR_LIT>' ) <EOL> } ) <EOL> return queryset . annotate ( ** { <EOL> alias : aggregator ( '<STR_LIT>' % query_name ) <EOL> } ) . order_by ( ordering ) <EOL> else : <EOL> return generic_annotate ( <EOL> queryset , <EOL> self , <EOL> aggregator ( '<STR_LIT>' ) , <EOL> related_field , <EOL> alias = alias <EOL> ) . order_by ( ordering ) <EOL> class _RatingsDescriptor ( models . Manager ) : <EOL> def __init__ ( self , rated_model , rating_model , rating_field ) : <EOL> self . rated_model = rated_model <EOL> self . rating_model = rating_model <EOL> self . rating_field = rating_field <EOL> def __get__ ( self , instance , instance_type = None ) : <EOL> if instance is None : <EOL> return self <EOL> return self . create_manager ( instance , <EOL> self . rating_model . _default_manager . __class__ ) <EOL> def __set__ ( self , instance , value ) : <EOL> if instance is None : <EOL> raise AttributeError ( "<STR_LIT>" ) <EOL> manager = self . __get__ ( instance ) <EOL> manager . add ( * value ) <EOL> def get_query_set ( self ) : <EOL> base_filters = self . rating_model . base_kwargs ( self . rated_model ) <EOL> qs = RatingsQuerySet ( self . rating_model , rated_model = self . rated_model ) <EOL> return qs . filter ( ** base_filters ) <EOL> def delete_manager ( self , instance ) : <EOL> """<STR_LIT>""" <EOL> return self . create_manager ( instance , <EOL> self . rating_model . _base_manager . __class__ ) <EOL> def create_manager ( self , instance , superclass ) : <EOL> """<STR_LIT>""" <EOL> rel_model = self . rating_model <EOL> rated_model = self . rated_model <EOL> class RelatedManager ( superclass ) : <EOL> def get_query_set ( self ) : <EOL> qs = RatingsQuerySet ( rel_model , rated_model = rated_model ) <EOL> return qs . filter ( ** ( self . core_filters ) ) <EOL> def add ( self , * objs ) : <EOL> lookup_kwargs = rel_model . lookup_kwargs ( instance ) <EOL> for obj in objs : <EOL> if not isinstance ( obj , self . model ) : <EOL> raise TypeError ( "<STR_LIT>" % <EOL> self . model . _meta . object_name ) <EOL> for ( k , v ) in lookup_kwargs . iteritems ( ) : <EOL> setattr ( obj , k , v ) <EOL> obj . save ( ) <EOL> add . alters_data = True <EOL> def create ( self , ** kwargs ) : <EOL> kwargs . update ( rel_model . lookup_kwargs ( instance ) ) <EOL> return super ( RelatedManager , self ) . create ( ** kwargs ) <EOL> create . alters_data = True <EOL> def get_or_create ( self , ** kwargs ) : <EOL> kwargs . update ( rel_model . lookup_kwargs ( instance ) ) <EOL> return super ( RelatedManager , self ) . get_or_create ( ** kwargs ) <EOL> get_or_create . alters_data = True <EOL> def remove ( self , * objs ) : <EOL> for obj in objs : <EOL> if obj in self . all ( ) : <EOL> obj . delete ( ) <EOL> else : <EOL> raise rel_model . DoesNotExist ( <EOL> "<STR_LIT>" % ( obj , instance ) ) <EOL> remove . alters_data = True <EOL> def clear ( self ) : <EOL> self . all ( ) . delete ( ) <EOL> clear . alters_data = True <EOL> def rate ( self , user , score ) : <EOL> rating , created = self . get_or_create ( user = user ) <EOL> if created or score != rating . score : <EOL> rating . score = score <EOL> rating . save ( ) <EOL> return rating <EOL> def unrate ( self , user ) : <EOL> return self . filter ( user = user , <EOL> ** rel_model . lookup_kwargs ( instance ) <EOL> ) . delete ( ) <EOL> def perform_aggregation ( self , aggregator ) : <EOL> score = self . all ( ) . aggregate ( agg = aggregator ( '<STR_LIT>' ) ) <EOL> return score [ '<STR_LIT>' ] <EOL> def cumulative_score ( self ) : <EOL> return self . perform_aggregation ( models . Sum ) <EOL> def average_score ( self ) : <EOL> return self . perform_aggregation ( models . Avg ) <EOL> def standard_deviation ( self ) : <EOL> return self . perform_aggregation ( models . StdDev ) <EOL> def variance ( self ) : <EOL> return self . perform_aggregation ( models . Variance ) <EOL> def similar_items ( self ) : <EOL> return SimilarItem . objects . get_for_item ( instance ) <EOL> manager = RelatedManager ( ) <EOL> manager . core_filters = rel_model . lookup_kwargs ( instance ) <EOL> manager . model = rel_model <EOL> return manager <EOL> def get_content_object_field ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _content_object_field = get_content_object_field ( self . rating_model ) <EOL> return self . _content_object_field <EOL> @ property <EOL> def is_gfk ( self ) : <EOL> return is_gfk ( self . get_content_object_field ( ) ) <EOL> def update_similar_items ( self ) : <EOL> from ratings . utils import calculate_similar_items <EOL> calculate_similar_items ( self . all ( ) ) <EOL> def similar_items ( self , item ) : <EOL> return SimilarItem . objects . get_for_item ( item ) <EOL> def recommended_items ( self , user ) : <EOL> return recommended_items ( self . all ( ) , user ) <EOL> def order_by_rating ( self , aggregator = models . Sum , descending = True , <EOL> queryset = None , alias = '<STR_LIT>' ) : <EOL> return self . all ( ) . order_by_rating ( <EOL> aggregator , descending , queryset , alias <EOL> ) <EOL> class SimilarItemManager ( models . Manager ) : <EOL> def get_for_item ( self , instance ) : <EOL> ctype = ContentType . objects . get_for_model ( instance ) <EOL> qs = self . filter ( content_type = ctype , object_id = instance . pk ) <EOL> return qs . order_by ( '<STR_LIT>' ) <EOL> class SimilarItem ( models . Model ) : <EOL> content_type = models . ForeignKey ( ContentType , related_name = '<STR_LIT>' ) <EOL> object_id = models . IntegerField ( ) <EOL> content_object = GenericForeignKey ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> similar_content_type = models . ForeignKey ( ContentType , <EOL> related_name = '<STR_LIT>' ) <EOL> similar_object_id = models . IntegerField ( ) <EOL> similar_object = GenericForeignKey ( '<STR_LIT>' , <EOL> '<STR_LIT>' ) <EOL> score = models . FloatField ( default = <NUM_LIT:0> ) <EOL> objects = SimilarItemManager ( ) <EOL> def __unicode__ ( self ) : <EOL> return u'<STR_LIT>' % ( self . similar_object , self . score ) </s>
