<s> import django <EOL> from django . conf import settings <EOL> from django . db import router <EOL> from django . db import transaction <EOL> from django . db import models <EOL> from django . db . models import signals <EOL> from django . db . models . fields . related import add_lazy_relation <EOL> from django . db . models . fields . related import ManyToManyField <EOL> from django . db . models . fields . related import RECURSIVE_RELATIONSHIP_CONSTANT <EOL> from django . utils import six <EOL> from django . utils . functional import cached_property , curry <EOL> from . compat import create_forward_many_to_many_manager <EOL> from . compat import get_foreignkey_field_kwargs <EOL> from . compat import get_model_name <EOL> from . forms import SortedMultipleChoiceField <EOL> SORT_VALUE_FIELD_NAME = '<STR_LIT>' <EOL> if hasattr ( transaction , '<STR_LIT>' ) : <EOL> atomic = transaction . atomic <EOL> else : <EOL> class atomic ( object ) : <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> pass <EOL> def __enter__ ( self ) : <EOL> pass <EOL> def __exit__ ( self , exc_type , exc_val , exc_tb ) : <EOL> pass <EOL> def create_sorted_many_related_manager ( superclass , rel , * args , ** kwargs ) : <EOL> RelatedManager = create_forward_many_to_many_manager ( <EOL> superclass , rel , * args , ** kwargs ) <EOL> class SortedRelatedManager ( RelatedManager ) : <EOL> def get_queryset ( self ) : <EOL> try : <EOL> return self . instance . _prefetched_objects_cache [ self . prefetch_cache_name ] <EOL> except ( AttributeError , KeyError ) : <EOL> if not hasattr ( RelatedManager , '<STR_LIT>' ) : <EOL> queryset = super ( SortedRelatedManager , self ) . get_query_set ( ) <EOL> else : <EOL> queryset = super ( SortedRelatedManager , self ) . get_queryset ( ) <EOL> return queryset . extra ( order_by = [ '<STR_LIT>' % ( <EOL> rel . through . _meta . db_table , <EOL> rel . through . _sort_field_name , <EOL> ) ] ) <EOL> get_query_set = get_queryset <EOL> if not hasattr ( RelatedManager , '<STR_LIT>' ) : <EOL> @ property <EOL> def _fk_val ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> return self . _pk_val <EOL> return self . related_val [ <NUM_LIT:0> ] <EOL> def get_prefetch_queryset ( self , instances , queryset = None ) : <EOL> if django . VERSION < ( <NUM_LIT:1> , <NUM_LIT:6> ) : <EOL> result = super ( SortedRelatedManager , self ) . get_prefetch_query_set ( instances ) <EOL> elif django . VERSION < ( <NUM_LIT:1> , <NUM_LIT:7> ) : <EOL> result = super ( SortedRelatedManager , self ) . get_prefetch_queryset ( instances ) <EOL> else : <EOL> result = super ( SortedRelatedManager , self ) . get_prefetch_queryset ( instances , queryset ) <EOL> queryset = result [ <NUM_LIT:0> ] <EOL> queryset . query . extra_order_by = [ <EOL> '<STR_LIT>' % ( <EOL> rel . through . _meta . db_table , <EOL> rel . through . _sort_field_name , <EOL> ) ] <EOL> return ( queryset , ) + result [ <NUM_LIT:1> : ] <EOL> get_prefetch_query_set = get_prefetch_queryset <EOL> def set ( self , objs , ** kwargs ) : <EOL> kwargs [ '<STR_LIT>' ] = True <EOL> super ( SortedRelatedManager , self ) . set ( objs , ** kwargs ) <EOL> set . alters_data = True <EOL> def _add_items ( self , source_field_name , target_field_name , * objs ) : <EOL> from django . db . models import Max , Model <EOL> if objs : <EOL> new_ids = [ ] <EOL> for obj in objs : <EOL> if isinstance ( obj , self . model ) : <EOL> if not router . allow_relation ( obj , self . instance ) : <EOL> raise ValueError ( <EOL> '<STR_LIT>' % <EOL> ( obj , self . instance . _state . db , obj . _state . db ) <EOL> ) <EOL> if hasattr ( self , '<STR_LIT>' ) : <EOL> fk_val = self . _get_fk_val ( obj , target_field_name ) <EOL> if fk_val is None : <EOL> raise ValueError ( '<STR_LIT>' % <EOL> ( obj , target_field_name ) ) <EOL> new_ids . append ( self . _get_fk_val ( obj , target_field_name ) ) <EOL> else : <EOL> new_ids . append ( obj . pk ) <EOL> elif isinstance ( obj , Model ) : <EOL> raise TypeError ( <EOL> "<STR_LIT>" % <EOL> ( self . model . _meta . object_name , obj ) <EOL> ) <EOL> else : <EOL> new_ids . append ( obj ) <EOL> db = router . db_for_write ( self . through , instance = self . instance ) <EOL> manager = self . through . _default_manager . using ( db ) <EOL> vals = ( manager <EOL> . values_list ( target_field_name , flat = True ) <EOL> . filter ( ** { <EOL> source_field_name : self . _fk_val , <EOL> '<STR_LIT>' % target_field_name : new_ids , <EOL> } ) ) <EOL> for val in vals : <EOL> if val in new_ids : <EOL> new_ids . remove ( val ) <EOL> _new_ids = [ ] <EOL> for pk in new_ids : <EOL> if pk not in _new_ids : <EOL> _new_ids . append ( pk ) <EOL> new_ids = _new_ids <EOL> new_ids_set = set ( new_ids ) <EOL> if self . reverse or source_field_name == self . source_field_name : <EOL> signals . m2m_changed . send ( sender = rel . through , action = '<STR_LIT>' , <EOL> instance = self . instance , reverse = self . reverse , <EOL> model = self . model , pk_set = new_ids_set , using = db ) <EOL> with atomic ( using = db ) : <EOL> fk_val = self . _fk_val <EOL> source_queryset = manager . filter ( ** { '<STR_LIT>' % source_field_name : fk_val } ) <EOL> sort_field_name = self . through . _sort_field_name <EOL> sort_value_max = source_queryset . aggregate ( max = Max ( sort_field_name ) ) [ '<STR_LIT>' ] or <NUM_LIT:0> <EOL> manager . bulk_create ( [ <EOL> self . through ( ** { <EOL> '<STR_LIT>' % source_field_name : fk_val , <EOL> '<STR_LIT>' % target_field_name : pk , <EOL> sort_field_name : sort_value_max + i + <NUM_LIT:1> , <EOL> } ) <EOL> for i , pk in enumerate ( new_ids ) <EOL> ] ) <EOL> if self . reverse or source_field_name == self . source_field_name : <EOL> signals . m2m_changed . send ( sender = rel . through , action = '<STR_LIT>' , <EOL> instance = self . instance , reverse = self . reverse , <EOL> model = self . model , pk_set = new_ids_set , using = db ) <EOL> return SortedRelatedManager <EOL> try : <EOL> from django . db . models . fields . related_descriptors import ManyToManyDescriptor <EOL> class SortedManyToManyDescriptor ( ManyToManyDescriptor ) : <EOL> def __init__ ( self , field ) : <EOL> super ( SortedManyToManyDescriptor , self ) . __init__ ( field . remote_field ) <EOL> @ cached_property <EOL> def related_manager_cls ( self ) : <EOL> model = self . rel . model <EOL> return create_sorted_many_related_manager ( <EOL> model . _default_manager . __class__ , <EOL> self . rel , <EOL> reverse = False , <EOL> ) <EOL> except ImportError : <EOL> from django . db . models . fields . related import ReverseManyRelatedObjectsDescriptor <EOL> class SortedManyToManyDescriptor ( ReverseManyRelatedObjectsDescriptor ) : <EOL> @ cached_property <EOL> def related_manager_cls ( self ) : <EOL> return create_sorted_many_related_manager ( <EOL> self . field . rel . to . _default_manager . __class__ , <EOL> self . field . rel <EOL> ) <EOL> class SortedManyToManyField ( ManyToManyField ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , to , sorted = True , ** kwargs ) : <EOL> self . sorted = sorted <EOL> self . sort_value_field_name = kwargs . pop ( <EOL> '<STR_LIT>' , <EOL> SORT_VALUE_FIELD_NAME ) <EOL> super ( SortedManyToManyField , self ) . __init__ ( to , ** kwargs ) <EOL> if self . sorted : <EOL> self . help_text = kwargs . get ( '<STR_LIT>' , None ) <EOL> def deconstruct ( self ) : <EOL> name , path , args , kwargs = super ( SortedManyToManyField , self ) . deconstruct ( ) <EOL> if self . sort_value_field_name is not SORT_VALUE_FIELD_NAME : <EOL> kwargs [ '<STR_LIT>' ] = self . sort_value_field_name <EOL> if self . sorted is not True : <EOL> kwargs [ '<STR_LIT>' ] = self . sorted <EOL> return name , path , args , kwargs <EOL> def contribute_to_class ( self , cls , name , ** kwargs ) : <EOL> if not self . sorted : <EOL> return super ( SortedManyToManyField , self ) . contribute_to_class ( cls , name , ** kwargs ) <EOL> if self . rel . symmetrical and ( self . rel . to == "<STR_LIT>" or self . rel . to == cls . _meta . object_name ) : <EOL> self . rel . related_name = "<STR_LIT>" % name <EOL> super ( ManyToManyField , self ) . contribute_to_class ( cls , name , ** kwargs ) <EOL> if not self . rel . through and not cls . _meta . abstract : <EOL> self . rel . through = self . create_intermediate_model ( cls ) <EOL> setattr ( cls , self . name , SortedManyToManyDescriptor ( self ) ) <EOL> self . m2m_db_table = curry ( self . _get_m2m_db_table , cls . _meta ) <EOL> if isinstance ( self . rel . through , six . string_types ) : <EOL> def resolve_through_model ( field , model , cls ) : <EOL> field . rel . through = model <EOL> add_lazy_relation ( cls , self , self . rel . through , resolve_through_model ) <EOL> if hasattr ( cls . _meta , '<STR_LIT>' ) : <EOL> if isinstance ( self . rel . to , six . string_types ) : <EOL> target = self . rel . to <EOL> else : <EOL> target = self . rel . to . _meta . db_table <EOL> cls . _meta . duplicate_targets [ self . column ] = ( target , "<STR_LIT>" ) <EOL> def get_internal_type ( self ) : <EOL> return '<STR_LIT>' <EOL> def formfield ( self , ** kwargs ) : <EOL> defaults = { } <EOL> if self . sorted : <EOL> defaults [ '<STR_LIT>' ] = SortedMultipleChoiceField <EOL> defaults . update ( kwargs ) <EOL> return super ( SortedManyToManyField , self ) . formfield ( ** defaults ) <EOL> def get_intermediate_model_name ( self , klass ) : <EOL> return '<STR_LIT>' % ( klass . _meta . object_name , self . name ) <EOL> def get_intermediate_model_meta_class ( self , klass , from_field_name , <EOL> to_field_name , <EOL> sort_value_field_name ) : <EOL> managed = True <EOL> to_model = self . rel . to <EOL> if isinstance ( self . rel . to , six . string_types ) : <EOL> if self . rel . to != RECURSIVE_RELATIONSHIP_CONSTANT : <EOL> def set_managed ( field , model , cls ) : <EOL> field . rel . through . _meta . managed = model . _meta . managed or cls . _meta . managed <EOL> add_lazy_relation ( klass , self , to_model , set_managed ) <EOL> else : <EOL> managed = klass . _meta . managed <EOL> else : <EOL> managed = klass . _meta . managed or to_model . _meta . managed <EOL> options = { <EOL> '<STR_LIT>' : self . _get_m2m_db_table ( klass . _meta ) , <EOL> '<STR_LIT>' : managed , <EOL> '<STR_LIT>' : klass , <EOL> '<STR_LIT>' : klass . _meta . app_label , <EOL> '<STR_LIT>' : klass . _meta . db_tablespace , <EOL> '<STR_LIT>' : ( ( from_field_name , to_field_name ) , ) , <EOL> '<STR_LIT>' : ( sort_value_field_name , ) , <EOL> '<STR_LIT>' : '<STR_LIT>' % { '<STR_LIT>' : from_field_name , '<STR_LIT:to>' : to_field_name } , <EOL> '<STR_LIT>' : '<STR_LIT>' % { '<STR_LIT>' : from_field_name , '<STR_LIT:to>' : to_field_name } , <EOL> } <EOL> if hasattr ( self . model . _meta , '<STR_LIT>' ) : <EOL> options . update ( { <EOL> '<STR_LIT>' : self . model . _meta . apps , <EOL> } ) <EOL> return type ( str ( '<STR_LIT:Meta>' ) , ( object , ) , options ) <EOL> def get_rel_to_model_and_object_name ( self , klass ) : <EOL> if isinstance ( self . rel . to , six . string_types ) : <EOL> if self . rel . to != RECURSIVE_RELATIONSHIP_CONSTANT : <EOL> to_model = self . rel . to <EOL> to_object_name = to_model . split ( '<STR_LIT:.>' ) [ - <NUM_LIT:1> ] <EOL> else : <EOL> to_model = klass <EOL> to_object_name = to_model . _meta . object_name <EOL> else : <EOL> to_model = self . rel . to <EOL> to_object_name = to_model . _meta . object_name <EOL> return to_model , to_object_name <EOL> def get_intermediate_model_sort_value_field ( self , klass ) : <EOL> field_name = self . sort_value_field_name <EOL> field = models . IntegerField ( default = <NUM_LIT:0> ) <EOL> return field_name , field <EOL> def get_intermediate_model_from_field ( self , klass ) : <EOL> name = self . get_intermediate_model_name ( klass ) <EOL> to_model , to_object_name = self . get_rel_to_model_and_object_name ( klass ) <EOL> if self . rel . to == RECURSIVE_RELATIONSHIP_CONSTANT or to_object_name == klass . _meta . object_name : <EOL> field_name = '<STR_LIT>' % to_object_name . lower ( ) <EOL> else : <EOL> field_name = get_model_name ( klass ) <EOL> field = models . ForeignKey ( klass , related_name = '<STR_LIT>' % name , <EOL> ** get_foreignkey_field_kwargs ( self ) ) <EOL> return field_name , field <EOL> def get_intermediate_model_to_field ( self , klass ) : <EOL> name = self . get_intermediate_model_name ( klass ) <EOL> to_model , to_object_name = self . get_rel_to_model_and_object_name ( klass ) <EOL> if self . rel . to == RECURSIVE_RELATIONSHIP_CONSTANT or to_object_name == klass . _meta . object_name : <EOL> field_name = '<STR_LIT>' % to_object_name . lower ( ) <EOL> else : <EOL> field_name = to_object_name . lower ( ) <EOL> field = models . ForeignKey ( to_model , related_name = '<STR_LIT>' % name , <EOL> ** get_foreignkey_field_kwargs ( self ) ) <EOL> return field_name , field <EOL> def create_intermediate_model_from_attrs ( self , klass , attrs ) : <EOL> name = self . get_intermediate_model_name ( klass ) <EOL> return type ( str ( name ) , ( models . Model , ) , attrs ) <EOL> def create_intermediate_model ( self , klass ) : <EOL> from_field_name , from_field = self . get_intermediate_model_from_field ( klass ) <EOL> to_field_name , to_field = self . get_intermediate_model_to_field ( klass ) <EOL> sort_value_field_name , sort_value_field = self . get_intermediate_model_sort_value_field ( klass ) <EOL> meta = self . get_intermediate_model_meta_class ( <EOL> klass , from_field_name , to_field_name , sort_value_field_name ) <EOL> attrs = { <EOL> '<STR_LIT:Meta>' : meta , <EOL> '<STR_LIT>' : klass . __module__ , <EOL> from_field_name : from_field , <EOL> to_field_name : to_field , <EOL> sort_value_field_name : sort_value_field , <EOL> '<STR_LIT>' : sort_value_field_name , <EOL> '<STR_LIT>' : from_field_name , <EOL> '<STR_LIT>' : to_field_name , <EOL> } <EOL> return self . create_intermediate_model_from_attrs ( klass , attrs ) <EOL> try : <EOL> import south <EOL> except ImportError : <EOL> south = None <EOL> if south is not None and '<STR_LIT>' in settings . INSTALLED_APPS : <EOL> from south . modelsinspector import add_introspection_rules <EOL> add_introspection_rules ( <EOL> [ ( <EOL> ( SortedManyToManyField , ) , <EOL> [ ] , <EOL> { "<STR_LIT>" : [ "<STR_LIT>" , { "<STR_LIT:default>" : True } ] } , <EOL> ) ] , <EOL> [ r'<STR_LIT>' ] <EOL> ) <EOL> import south . creator . actions <EOL> from south . creator . freezer import model_key <EOL> class AddM2M ( south . creator . actions . AddM2M ) : <EOL> SORTED_FORWARDS_TEMPLATE = '''<STR_LIT>''' <EOL> def console_line ( self ) : <EOL> if isinstance ( self . field , SortedManyToManyField ) and self . field . sorted : <EOL> return "<STR_LIT>" % ( <EOL> self . field . name , <EOL> self . model . _meta . app_label , <EOL> self . model . _meta . object_name , <EOL> ) <EOL> else : <EOL> return super ( AddM2M , self ) . console_line ( ) <EOL> def forwards_code ( self ) : <EOL> if isinstance ( self . field , SortedManyToManyField ) and self . field . sorted : <EOL> return self . SORTED_FORWARDS_TEMPLATE % { <EOL> "<STR_LIT>" : self . model . _meta . object_name , <EOL> "<STR_LIT>" : self . field . name , <EOL> "<STR_LIT>" : self . field . m2m_db_table ( ) , <EOL> "<STR_LIT>" : self . field . m2m_column_name ( ) [ : - <NUM_LIT:3> ] , <EOL> "<STR_LIT>" : self . field . m2m_column_name ( ) , <EOL> "<STR_LIT>" : model_key ( self . model ) , <EOL> "<STR_LIT>" : self . field . m2m_reverse_name ( ) [ : - <NUM_LIT:3> ] , <EOL> "<STR_LIT>" : self . field . m2m_reverse_name ( ) , <EOL> "<STR_LIT>" : model_key ( self . field . rel . to ) , <EOL> "<STR_LIT>" : self . field . sort_value_field_name , <EOL> } <EOL> else : <EOL> return super ( AddM2M , self ) . forwards_code ( ) <EOL> class DeleteM2M ( AddM2M ) : <EOL> def console_line ( self ) : <EOL> return "<STR_LIT>" % ( <EOL> self . field . name , <EOL> self . model . _meta . app_label , <EOL> self . model . _meta . object_name , <EOL> ) <EOL> def forwards_code ( self ) : <EOL> return AddM2M . backwards_code ( self ) <EOL> def backwards_code ( self ) : <EOL> return AddM2M . forwards_code ( self ) <EOL> south . creator . actions . AddM2M = AddM2M <EOL> south . creator . actions . DeleteM2M = DeleteM2M </s>
