<s> """<STR_LIT>""" <EOL> from builtins import str <EOL> import logging <EOL> logger = logging . getLogger ( __name__ ) <EOL> from django . db import models <EOL> from django . db import router <EOL> from django . db . models . deletion import Collector , DO_NOTHING <EOL> from django . core . exceptions import ValidationError <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from lino . core . utils import resolve_model <EOL> from lino . core . fields import VirtualField <EOL> from lino . core . signals import pre_remove_child , pre_add_child <EOL> from lino import AFTER17 <EOL> class ChildCollector ( Collector ) : <EOL> """<STR_LIT>""" <EOL> def collect ( self , objs , source = None , nullable = False , collect_related = True , <EOL> source_attr = None , reverse_dependency = False ) : <EOL> if self . can_fast_delete ( objs ) : <EOL> self . fast_deletes . append ( objs ) <EOL> return <EOL> new_objs = self . add ( objs , source , nullable , <EOL> reverse_dependency = reverse_dependency ) <EOL> if not new_objs : <EOL> return <EOL> model = new_objs [ <NUM_LIT:0> ] . __class__ <EOL> if collect_related : <EOL> for related in model . _meta . get_all_related_objects ( <EOL> include_hidden = True , include_proxy_eq = True , <EOL> local_only = True ) : <EOL> field = related . field <EOL> if field . rel . on_delete == DO_NOTHING : <EOL> continue <EOL> sub_objs = self . related_objects ( related , new_objs ) <EOL> if self . can_fast_delete ( sub_objs , from_field = field ) : <EOL> self . fast_deletes . append ( sub_objs ) <EOL> elif sub_objs : <EOL> field . rel . on_delete ( self , field , sub_objs , self . using ) <EOL> for field in model . _meta . virtual_fields : <EOL> if hasattr ( field , '<STR_LIT>' ) : <EOL> sub_objs = field . bulk_related_objects ( new_objs , self . using ) <EOL> self . collect ( sub_objs , <EOL> source = model , <EOL> source_attr = field . rel . related_name , <EOL> nullable = True ) <EOL> class OldChildCollector ( Collector ) : <EOL> def collect ( self , objs , source = None , nullable = False , collect_related = True , <EOL> source_attr = None , collect_parents = True ) : <EOL> new_objs = self . add ( objs , source , nullable ) <EOL> if not new_objs : <EOL> return <EOL> model = new_objs [ <NUM_LIT:0> ] . __class__ <EOL> if collect_related : <EOL> for related in model . _meta . get_all_related_objects ( include_hidden = True , local_only = True ) : <EOL> field = related . field <EOL> if related . model . _meta . auto_created : <EOL> self . add_batch ( related . model , field , new_objs ) <EOL> else : <EOL> sub_objs = self . related_objects ( related , new_objs ) <EOL> if not sub_objs : <EOL> continue <EOL> field . rel . on_delete ( self , field , sub_objs , self . using ) <EOL> for relation in model . _meta . many_to_many : <EOL> if not relation . rel . through : <EOL> sub_objs = relation . bulk_related_objects ( <EOL> new_objs , self . using ) <EOL> self . collect ( sub_objs , <EOL> source = model , <EOL> source_attr = relation . rel . related_name , <EOL> nullable = True ) <EOL> def get_child ( obj , child_model ) : <EOL> if obj . pk is not None : <EOL> try : <EOL> return child_model . objects . get ( pk = obj . pk ) <EOL> except child_model . DoesNotExist : <EOL> return None <EOL> def delete_child ( obj , child_model , ar = None , using = None ) : <EOL> """<STR_LIT>""" <EOL> using = using or router . db_for_write ( obj . __class__ , instance = obj ) <EOL> child = get_child ( obj , child_model ) <EOL> if child is None : <EOL> raise Exception ( "<STR_LIT>" % ( obj , child_model . __name__ ) ) <EOL> ignore_models = set ( ) <EOL> msg = child . _lino_ddh . disable_delete_on_object ( <EOL> obj , ignore_models ) <EOL> if msg : <EOL> raise ValidationError ( msg ) <EOL> if True : <EOL> collector = ChildCollector ( using = using ) <EOL> collector . collect ( [ child ] ) <EOL> else : <EOL> collector = ChildCollector ( using = using ) <EOL> collector . collect ( [ child ] , source = obj . __class__ , <EOL> nullable = True , collect_parents = False ) <EOL> collector . delete ( ) <EOL> def insert_child ( obj , child_model , full_clean = False , ** attrs ) : <EOL> """<STR_LIT>""" <EOL> parent_link_field = child_model . _meta . parents . get ( obj . __class__ , None ) <EOL> if parent_link_field is None : <EOL> raise ValidationError ( str ( "<STR_LIT>" % ( <EOL> obj . __class__ . __name__ , child_model . __name__ ) ) ) <EOL> attrs [ parent_link_field . name ] = obj <EOL> if AFTER17 : <EOL> fields_list = obj . _meta . concrete_fields <EOL> else : <EOL> fields_list = obj . _meta . fields <EOL> for field in fields_list : <EOL> attrs [ field . name ] = getattr ( obj , field . name ) <EOL> new_obj = child_model ( ** attrs ) <EOL> new_obj . save ( ) <EOL> if full_clean : <EOL> try : <EOL> new_obj . full_clean ( ) <EOL> new_obj . save ( ) <EOL> except ValidationError as e : <EOL> msg = obj . error2str ( e ) <EOL> raise ValidationError ( <EOL> _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) % <EOL> dict ( child = child_model . __name__ , <EOL> parent = obj . __class__ . __name__ , <EOL> message = msg ) ) <EOL> return new_obj <EOL> class EnableChild ( VirtualField ) : <EOL> """<STR_LIT>""" <EOL> editable = True <EOL> def __init__ ( self , child_model , ** kw ) : <EOL> raise Exception ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> kw . update ( default = False ) <EOL> self . child_model = child_model <EOL> VirtualField . __init__ ( self , models . BooleanField ( ** kw ) , self . has_child ) <EOL> def is_enabled ( self , lh ) : <EOL> """<STR_LIT>""" <EOL> return lh . layout . _datasource . model != self . child_model and issubclass ( self . child_model , lh . layout . _datasource . model ) <EOL> def attach_to_model ( self , model , name ) : <EOL> self . child_model = resolve_model ( <EOL> self . child_model , model . _meta . app_label ) <EOL> VirtualField . attach_to_model ( self , model , name ) <EOL> def has_child ( self , obj , request = None ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> getattr ( obj , self . child_model . __name__ . lower ( ) ) <EOL> except self . child_model . DoesNotExist : <EOL> return False <EOL> return True <EOL> def set_value_in_object ( self , ar , obj , v ) : <EOL> if self . has_child ( obj ) : <EOL> if not v : <EOL> if ar is not None : <EOL> pre_remove_child . send ( <EOL> sender = obj , request = ar . request , <EOL> child = self . child_model ) <EOL> delete_child ( obj , self . child_model , ar ) <EOL> else : <EOL> if v : <EOL> if ar is not None : <EOL> pre_add_child . send ( <EOL> sender = obj , request = ar . request , <EOL> child = self . child_model ) <EOL> insert_child ( obj , self . child_model , full_clean = True ) <EOL> from lino . utils . dpy import create_mti_child as create_child </s>
