app/django/db/models/related.py
changeset 323 ff1a9aa48cfd
parent 54 03e267d67478
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
    13     def __init__(self, parent_model, model, field):
    13     def __init__(self, parent_model, model, field):
    14         self.parent_model = parent_model
    14         self.parent_model = parent_model
    15         self.model = model
    15         self.model = model
    16         self.opts = model._meta
    16         self.opts = model._meta
    17         self.field = field
    17         self.field = field
    18         self.edit_inline = field.rel.edit_inline
       
    19         self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
    18         self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
    20         self.var_name = self.opts.object_name.lower()
    19         self.var_name = self.opts.object_name.lower()
    21 
       
    22     def flatten_data(self, follow, obj=None):
       
    23         new_data = {}
       
    24         rel_instances = self.get_list(obj)
       
    25         for i, rel_instance in enumerate(rel_instances):
       
    26             instance_data = {}
       
    27             for f in self.opts.fields + self.opts.many_to_many:
       
    28                 # TODO: Fix for recursive manipulators.
       
    29                 fol = follow.get(f.name, None)
       
    30                 if fol:
       
    31                     field_data = f.flatten_data(fol, rel_instance)
       
    32                     for name, value in field_data.items():
       
    33                         instance_data['%s.%d.%s' % (self.var_name, i, name)] = value
       
    34             new_data.update(instance_data)
       
    35         return new_data
       
    36 
       
    37     def extract_data(self, data):
       
    38         """
       
    39         Pull out the data meant for inline objects of this class,
       
    40         i.e. anything starting with our module name.
       
    41         """
       
    42         return data # TODO
       
    43 
       
    44     def get_list(self, parent_instance=None):
       
    45         "Get the list of this type of object from an instance of the parent class."
       
    46         if parent_instance is not None:
       
    47             attr = getattr(parent_instance, self.get_accessor_name())
       
    48             if self.field.rel.multiple:
       
    49                 # For many-to-many relationships, return a list of objects
       
    50                 # corresponding to the xxx_num_in_admin options of the field
       
    51                 objects = list(attr.all())
       
    52 
       
    53                 count = len(objects) + self.field.rel.num_extra_on_change
       
    54                 if self.field.rel.min_num_in_admin:
       
    55                     count = max(count, self.field.rel.min_num_in_admin)
       
    56                 if self.field.rel.max_num_in_admin:
       
    57                     count = min(count, self.field.rel.max_num_in_admin)
       
    58 
       
    59                 change = count - len(objects)
       
    60                 if change > 0:
       
    61                     return objects + [None] * change
       
    62                 if change < 0:
       
    63                     return objects[:change]
       
    64                 else: # Just right
       
    65                     return objects
       
    66             else:
       
    67                 # A one-to-one relationship, so just return the single related
       
    68                 # object
       
    69                 return [attr]
       
    70         else:
       
    71             if self.field.rel.min_num_in_admin:
       
    72                 return [None] * max(self.field.rel.num_in_admin, self.field.rel.min_num_in_admin)
       
    73             else:
       
    74                 return [None] * self.field.rel.num_in_admin
       
    75 
    20 
    76     def get_db_prep_lookup(self, lookup_type, value):
    21     def get_db_prep_lookup(self, lookup_type, value):
    77         # Defer to the actual field definition for db prep
    22         # Defer to the actual field definition for db prep
    78         return self.field.get_db_prep_lookup(lookup_type, value)
    23         return self.field.get_db_prep_lookup(lookup_type, value)
    79         
    24 
    80     def editable_fields(self):
    25     def editable_fields(self):
    81         "Get the fields in this class that should be edited inline."
    26         "Get the fields in this class that should be edited inline."
    82         return [f for f in self.opts.fields + self.opts.many_to_many if f.editable and f != self.field]
    27         return [f for f in self.opts.fields + self.opts.many_to_many if f.editable and f != self.field]
    83 
       
    84     def get_follow(self, override=None):
       
    85         if isinstance(override, bool):
       
    86             if override:
       
    87                 over = {}
       
    88             else:
       
    89                 return None
       
    90         else:
       
    91             if override:
       
    92                 over = override.copy()
       
    93             elif self.edit_inline:
       
    94                 over = {}
       
    95             else:
       
    96                 return None
       
    97 
       
    98         over[self.field.name] = False
       
    99         return self.opts.get_follow(over)
       
   100 
       
   101     def get_manipulator_fields(self, opts, manipulator, change, follow):
       
   102         if self.field.rel.multiple:
       
   103             if change:
       
   104                 attr = getattr(manipulator.original_object, self.get_accessor_name())
       
   105                 count = attr.count()
       
   106                 count += self.field.rel.num_extra_on_change
       
   107             else:
       
   108                 count = self.field.rel.num_in_admin
       
   109             if self.field.rel.min_num_in_admin:
       
   110                 count = max(count, self.field.rel.min_num_in_admin)
       
   111             if self.field.rel.max_num_in_admin:
       
   112                 count = min(count, self.field.rel.max_num_in_admin)
       
   113         else:
       
   114             count = 1
       
   115 
       
   116         fields = []
       
   117         for i in range(count):
       
   118             for f in self.opts.fields + self.opts.many_to_many:
       
   119                 if follow.get(f.name, False):
       
   120                     prefix = '%s.%d.' % (self.var_name, i)
       
   121                     fields.extend(f.get_manipulator_fields(self.opts, manipulator, change,
       
   122                                                            name_prefix=prefix, rel=True))
       
   123         return fields
       
   124 
    28 
   125     def __repr__(self):
    29     def __repr__(self):
   126         return "<RelatedObject: %s related to %s>" % (self.name, self.field.name)
    30         return "<RelatedObject: %s related to %s>" % (self.name, self.field.name)
   127 
    31 
   128     def bind(self, field_mapping, original, bound_related_object_class=BoundRelatedObject):
    32     def bind(self, field_mapping, original, bound_related_object_class=BoundRelatedObject):