<s> from django . db import models <EOL> from django . db . models . query import ValuesQuerySet <EOL> from django . utils import six <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from sellmo . utils . query import PKIterator <EOL> from sellmo . utils . text import call_or_format <EOL> from mptt . models import MPTTModel , TreeForeignKey , TreeManager <EOL> from mptt . querysets import TreeQuerySet <EOL> import polymorphism <EOL> from . . fields import AttributeKeyField , AttributeTypeField <EOL> from . . constants import VALUE_FORMAT <EOL> from . . types import types as attribute_types <EOL> import sellmo . contrib . attribute as _attribute <EOL> import sellmo . apps . product as _product <EOL> class SmartValueValuesQuerySet ( ValuesQuerySet ) : <EOL> def smart_sort ( self , attribute = None , product = None ) : <EOL> return self . all ( ) <EOL> def iterator ( self ) : <EOL> rows = [ ] <EOL> def get_used_value_type ( row , last_col = None ) : <EOL> if last_col : <EOL> typ = value_types . get ( last_col , None ) <EOL> if typ and not typ . is_empty ( row [ last_col ] ) : <EOL> return typ , last_col <EOL> for col in row : <EOL> typ = value_types . get ( col , None ) <EOL> if typ and not typ . is_empty ( row [ col ] ) : <EOL> return typ , col <EOL> return None , None <EOL> value_types = { <EOL> typ . get_value_field_name ( ) : typ <EOL> for typ in six . itervalues ( attribute_types ) <EOL> } <EOL> value_models = { <EOL> typ . get_model ( ) : set ( ) <EOL> for typ in six . itervalues ( attribute_types ) if typ . get_model ( ) <EOL> } <EOL> attributes = set ( ) <EOL> last_col = None <EOL> for row in super ( SmartValueValuesQuerySet , self ) . iterator ( ) : <EOL> if '<STR_LIT>' in row : <EOL> attributes . add ( row [ '<STR_LIT>' ] ) <EOL> typ , last_col = get_used_value_type ( row , last_col ) <EOL> if typ : <EOL> value = row [ typ . get_value_field_name ( ) ] <EOL> row [ '<STR_LIT:value>' ] = value <EOL> model = typ . get_model ( ) <EOL> if model : <EOL> value_models [ model ] . add ( value ) <EOL> else : <EOL> row [ '<STR_LIT:value>' ] = None <EOL> rows . append ( row ) <EOL> attributes = ( <EOL> { <EOL> obj . pk : obj <EOL> for obj in PKIterator ( <EOL> _attribute . models . Attribute , attributes <EOL> ) <EOL> } if attributes else { } <EOL> ) <EOL> value_models = { <EOL> model : ( <EOL> { <EOL> obj . pk : obj <EOL> for obj in PKIterator ( model , pks ) <EOL> } if pks else { } <EOL> ) <EOL> for model , pks in six . iteritems ( value_models ) <EOL> } <EOL> for row in rows : <EOL> if '<STR_LIT>' in row : <EOL> row [ '<STR_LIT>' ] = attributes [ row [ '<STR_LIT>' ] ] <EOL> typ , last_col = get_used_value_type ( row , last_col ) <EOL> if typ : <EOL> model = typ . get_model ( ) <EOL> if model : <EOL> row [ '<STR_LIT:value>' ] = value_models [ model ] [ row [ '<STR_LIT:value>' ] ] <EOL> yield row <EOL> class ValueQuerySet ( polymorphism . PolymorphicRelatedQuerySet ) : <EOL> def for_product ( self , product ) : <EOL> return self . filter ( product = product ) <EOL> def for_attribute ( self , attribute ) : <EOL> return self . filter ( attribute = attribute ) <EOL> def smart_values ( self , * fields ) : <EOL> fields = list ( fields ) <EOL> value_field_names = [ <EOL> typ . get_value_field_name ( ) <EOL> for typ in six . itervalues ( attribute_types ) <EOL> ] <EOL> if '<STR_LIT:value>' in fields : <EOL> fields . remove ( '<STR_LIT:value>' ) <EOL> fields . extend ( value_field_names ) <EOL> values = self . values ( * fields ) <EOL> values = values . _clone ( klass = SmartValueValuesQuerySet ) <EOL> return values . order_by ( * fields ) <EOL> class ValueManager ( models . Manager ) : <EOL> def get_by_natural_key ( self , attribute , product , value , queryset = None ) : <EOL> attribute = _attribute . models . Attribute . objects . get_by_natural_key ( <EOL> * attribute <EOL> ) <EOL> if queryset is None : <EOL> queryset = self . all ( ) <EOL> queryset = queryset . filter ( <EOL> attribute = attribute , <EOL> product = _product . models . Product . objects . get_by_natural_key ( <EOL> * product ) <EOL> ) <EOL> return attribute . get_type ( ) . get_value_by_natural_key ( queryset , * value ) <EOL> class Value ( models . Model ) : <EOL> attribute = models . ForeignKey ( <EOL> '<STR_LIT>' , <EOL> db_index = True , <EOL> verbose_name = _ ( u"<STR_LIT>" ) , <EOL> related_name = '<STR_LIT>' , <EOL> on_delete = models . PROTECT <EOL> ) <EOL> product = models . ForeignKey ( <EOL> '<STR_LIT>' , <EOL> db_index = True , <EOL> related_name = '<STR_LIT>' , <EOL> ) <EOL> def get_value ( self ) : <EOL> field_name = self . attribute . get_type ( ) . get_value_field_name ( ) <EOL> value = getattr ( self , field_name ) <EOL> return self . attribute . get_type ( ) . from_db_value ( value ) <EOL> def set_value ( self , value ) : <EOL> value = self . attribute . get_type ( ) . prep_db_value ( value ) <EOL> if value != self . get_value ( ) : <EOL> self . _old_value = self . get_value ( ) <EOL> field_name = self . attribute . get_type ( ) . get_value_field_name ( ) <EOL> setattr ( self , field_name , value ) <EOL> value = property ( get_value , set_value ) <EOL> _old_value = None <EOL> def get_old_value ( self ) : <EOL> if self . _old_value is None : <EOL> return self . get_value ( ) <EOL> return self . _old_value <EOL> old_value = property ( get_old_value ) <EOL> def is_empty ( self ) : <EOL> return self . attribute . get_type ( ) . is_empty ( self . get_value ( ) ) <EOL> def save_or_delete_value ( self ) : <EOL> if not self . is_empty ( ) : <EOL> self . save ( ) <EOL> elif not self . pk is None : <EOL> self . delete ( ) <EOL> def natural_key ( self ) : <EOL> return ( <EOL> self . attribute . natural_key ( ) , self . product . natural_key ( ) , <EOL> self . attribute . get_type ( ) . value_natural_key ( self . get_value ( ) ) <EOL> ) <EOL> natural_key . dependencies = [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> def __unicode__ ( self ) : <EOL> return call_or_format ( <EOL> VALUE_FORMAT , <EOL> value = self . value , <EOL> attribute = self . attribute <EOL> ) <EOL> class Meta : <EOL> abstract = True <EOL> app_label = '<STR_LIT>' <EOL> verbose_name = _ ( "<STR_LIT:value>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> class AttributeQuerySet ( models . QuerySet ) : <EOL> def for_attribute_set ( self , sett , recurse = True ) : <EOL> if recurse : <EOL> return self . filter ( <EOL> sets__in = sett . get_ancestors ( include_self = True ) <EOL> ) <EOL> else : <EOL> return self . filter ( sets__in = [ sett ] ) <EOL> def for_product ( self , product ) : <EOL> return self . filter ( values__product = product ) . distinct ( ) <EOL> class AttributeManager ( models . Manager ) : <EOL> def get_by_natural_key ( self , key ) : <EOL> return self . get ( key = key ) <EOL> class Attribute ( models . Model ) : <EOL> name = models . CharField ( max_length = <NUM_LIT:100> ) <EOL> key = AttributeKeyField ( max_length = <NUM_LIT:50> , db_index = True , blank = True ) <EOL> required = models . BooleanField ( default = False , verbose_name = _ ( "<STR_LIT>" ) , ) <EOL> sets = models . ManyToManyField ( <EOL> '<STR_LIT>' , <EOL> blank = True , <EOL> related_name = '<STR_LIT>' , <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> ) <EOL> visible = models . BooleanField ( default = True , verbose_name = _ ( "<STR_LIT>" ) , ) <EOL> indexed = models . BooleanField ( default = True , verbose_name = _ ( "<STR_LIT>" ) , ) <EOL> sort_order = models . SmallIntegerField ( <EOL> default = <NUM_LIT:0> , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> ) <EOL> def save ( self , * args , ** kwargs ) : <EOL> old = None <EOL> if self . pk : <EOL> old = _attribute . models . Attribute . objects . get ( pk = self . pk ) <EOL> elif not self . key : <EOL> self . key = AttributeKeyField . key_from_name ( self . name ) <EOL> if old is not None and old . values . count ( ) > <NUM_LIT:0> : <EOL> if self . type != old . type : <EOL> raise Exception ( <EOL> ( <EOL> _ ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) <EOL> ) <EOL> ) <EOL> super ( Attribute , self ) . save ( * args , ** kwargs ) <EOL> def get_type ( self ) : <EOL> return attribute_types [ self . type ] <EOL> def natural_key ( self ) : <EOL> return ( self . key , ) <EOL> def __unicode__ ( self ) : <EOL> return self . name <EOL> class Meta : <EOL> abstract = True <EOL> app_label = '<STR_LIT>' <EOL> ordering = [ '<STR_LIT>' , '<STR_LIT:name>' ] <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> class AttributeChoiceQuerySet ( models . QuerySet ) : <EOL> pass <EOL> class AttributeChoiceManager ( models . Manager ) : <EOL> def get_by_natural_key ( self , attribute , value ) : <EOL> attribute = _attribute . models . Attribute . objects . get_by_natural_key ( <EOL> * attribute <EOL> ) <EOL> queryset = self . filter ( attribute = attribute ) <EOL> return attribute . get_type ( ) . get_value_by_natural_key ( queryset , * value ) <EOL> class AttributeChoice ( models . Model ) : <EOL> attribute = models . ForeignKey ( <EOL> '<STR_LIT>' , <EOL> db_index = True , <EOL> verbose_name = _ ( u"<STR_LIT>" ) , <EOL> related_name = '<STR_LIT>' , <EOL> ) <EOL> def get_value ( self ) : <EOL> field_name = self . attribute . get_type ( ) . get_value_field_name ( ) <EOL> value = getattr ( self , field_name ) <EOL> return self . attribute . get_type ( ) . from_db_value ( value ) <EOL> def set_value ( self , value ) : <EOL> value = self . attribute . get_type ( ) . prep_db_value ( value ) <EOL> if value != self . get_value ( ) : <EOL> self . _old_value = self . get_value ( ) <EOL> field_name = self . attribute . get_type ( ) . get_value_field_name ( ) <EOL> setattr ( self , field_name , value ) <EOL> value = property ( get_value , set_value ) <EOL> def natural_key ( self ) : <EOL> return ( <EOL> self . attribute . natural_key ( ) , <EOL> self . attribute . get_type ( ) . value_natural_key ( self . get_value ( ) ) <EOL> ) <EOL> natural_key . dependencies = [ '<STR_LIT>' ] <EOL> def __unicode__ ( self ) : <EOL> return unicode ( self . value ) <EOL> class Meta : <EOL> abstract = True <EOL> app_label = '<STR_LIT>' <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> class AttributeSetQuerySet ( TreeQuerySet ) : <EOL> def in_parent ( self , sett , recurse = True ) : <EOL> q = self . filter ( tree_id = sett . tree_id ) <EOL> if recurse : <EOL> return q . filter ( level__gt = sett . level ) <EOL> else : <EOL> return q . filter ( level = sett . level + <NUM_LIT:1> ) <EOL> def flat_ordered ( self ) : <EOL> return self . order_by ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> class AttributeSetManager ( TreeManager ) : <EOL> def get_by_natural_key ( self , full_name ) : <EOL> parts = full_name . split ( '<STR_LIT:/>' ) <EOL> sett = None <EOL> for name in parts : <EOL> sett = self . get ( parent = sett , name = name ) <EOL> return sett <EOL> class AttributeSet ( MPTTModel ) : <EOL> sort_order = models . SmallIntegerField ( <EOL> default = <NUM_LIT:0> , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> ) <EOL> parent = TreeForeignKey ( <EOL> '<STR_LIT>' , <EOL> blank = True , <EOL> null = True , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> related_name = '<STR_LIT>' <EOL> ) <EOL> name = models . CharField ( max_length = <NUM_LIT:255> , verbose_name = _ ( "<STR_LIT:name>" ) , ) <EOL> def get_nodes ( self , ancestors = None ) : <EOL> if ancestors is None : <EOL> ancestors = self . get_ancestors ( include_self = True ) <EOL> else : <EOL> ancestors = ancestors + [ self ] <EOL> return ancestors <EOL> nodes = property ( get_nodes ) <EOL> def get_full_name ( self , ancestors = None ) : <EOL> return "<STR_LIT>" . join ( sett . name for sett in self . get_nodes ( ancestors ) ) <EOL> full_name = property ( get_full_name ) <EOL> def natural_key ( self ) : <EOL> return ( '<STR_LIT:/>' . join ( sett . name for sett in self . get_nodes ( ) ) , ) <EOL> def __unicode__ ( self ) : <EOL> return self . full_name <EOL> class MPTTMeta : <EOL> order_insertion_by = [ '<STR_LIT>' , '<STR_LIT:name>' ] <EOL> class Meta : <EOL> abstract = True <EOL> app_label = '<STR_LIT>' <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) </s>
