Django

Code

Changeset 773

Show
Ignore:
Timestamp:
10/04/05 11:35:39 (3 years ago)
Author:
rjwittams
Message:

Added templates for 'funny' widgets here: django/conf/admin_templates/widget
Added a follow argument to manipulators. This allows you to exclude/include fields and related objects ( recursively), defaulting to current behaviour, meaning that forms can modify a subset of fields. This should fix #445. Fixed update generic view to use this (will change others soon). Merged to trunk r772.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/new-admin/django/core/meta/fields.py

    r748 r773  
    640640 
    641641    def get_db_prep_save(self,value): 
    642         if value == '': 
    643             return None 
    644         else: 
    645             return int(value) 
    646      
     642       try: 
     643            if value == '' or None: 
     644                return None 
     645            else: 
     646                return int(value) 
     647       except Exception, e:  
     648            print "name: %s  val: %s" % (self.name, value)          
     649 
    647650    def flatten_data(self, obj = None): 
    648651        if not obj:  
  • django/branches/new-admin/django/core/meta/__init__.py

    r766 r773  
    148148 
    149149 
    150 class InlineRelatedObject(object): 
     150class RelatedObject(object): 
    151151    def __init__(self,parent_opts, opts, field): 
    152152        self.parent_opts = parent_opts 
    153153        self.opts = opts 
    154154        self.field = field 
     155        self.edit_inline = field.rel.edit_inline 
    155156        self.name = opts.module_name 
     157        self.var_name = opts.object_name.lower() 
    156158 
    157159    def flatten_data(self,obj = None): 
    158         var_name = self.opts.object_name.lower() 
    159160        new_data = {} 
    160161        rel_instances = self.get_list(obj) 
     
    166167                #if hasattr(f, 'editable') and f.editable and f != self.field: 
    167168                for name, value in field_data.items(): 
    168                     instance_data['%s.%d.%s' % (var_name, i, name)] = value 
     169                    instance_data['%s.%d.%s' % (self.var_name, i, name)] = value 
    169170            new_data.update(instance_data)              
    170171     
     
    205206         
    206207        return [wrapping_func(f) for f in self.opts.fields + self.opts.many_to_many if f.editable and f != self.field ] 
     208       
     209    def get_follow(self, override=None): 
     210        if override: 
     211            over = override.copy() 
     212        elif self.edit_inline: 
     213            over = {} 
     214        else: 
     215            return None 
    207216         
     217        over[self.field.name] = False 
     218        return self.opts.get_follow(over) 
     219     
     220     
    208221    def __repr__(self): 
    209         return "<InlineRelatedObject: %s related to %s>" % ( self.name, self.field.name)       
    210  
     222        return "<RelatedObject: %s related to %s>" % ( self.name, self.field.name)       
     223 
     224    def get_manipulator_fields(self, opts, manipulator, change, follow): 
     225        if change: 
     226            meth_name = 'get_%s_count' % self.parent_opts.get_rel_object_method_name(self.opts, self.field) 
     227            count = getattr(manipulator.original_object, meth_name)() 
     228            count += self.field.rel.num_extra_on_change 
     229            if self.field.rel.min_num_in_admin: 
     230                count = max(count, self.field.rel.min_num_in_admin) 
     231            if self.field.rel.max_num_in_admin: 
     232                count = min(count, self.field.rel.max_num_in_admin) 
     233        else: 
     234            count = self.field.rel.num_in_admin 
     235 
     236        fields = [] 
    211237         
     238 
     239        for i in range(count): 
     240            for f in self.opts.fields + self.opts.many_to_many: 
     241                    if follow.get(f.name, False): 
     242                        prefix = '%s.%d.' % (self.var_name, i) 
     243                        fields.extend( 
     244                             f.get_manipulator_fields(self.opts, manipulator, change, name_prefix=prefix, rel=True)) 
     245 
     246        return fields 
     247 
    212248 
    213249class Options: 
     
    383419 
    384420    def get_inline_related_objects_wrapped(self): 
    385         return [InlineRelatedObject(self, opts, field) for opts, field in self.get_all_related_objects() if field.rel.edit_inline] 
    386  
    387     def get_data_holders(self): 
    388         return self.fields + self.many_to_many + self.get_inline_related_objects_wrapped() 
     421        return [RelatedObject(self, opts, field) for opts, field in self.get_all_related_objects() if field.rel.edit_inline] 
     422 
     423    def get_all_related_objects_wrapped(self): 
     424        return [RelatedObject(self, opts, field) for opts, field in self.get_all_related_objects()] 
     425 
     426    def get_data_holders(self, follow=None): 
     427        return [f for f in self.fields + self.many_to_many + self.get_all_related_objects_wrapped() if follow.get(f.name, None) ] 
     428 
     429    def get_follow(self, override=None): 
     430        follow = {} 
     431         
     432        for f in self.fields + self.many_to_many: 
     433            if override and override.has_key(f.name): 
     434                fol = override[f.name] 
     435            else: 
     436                fol = f.editable 
     437            if fol: 
     438                follow[f.name] = fol 
     439  
     440        for f in self.get_all_related_objects_wrapped(): 
     441            if override and override.has_key(f.name): 
     442               fol = f.get_follow(override[f.name]) 
     443            else: 
     444               fol = f.get_follow(None) 
     445            if fol: 
     446                follow[f.name] = fol  
     447 
     448        return follow 
    389449 
    390450    def get_all_related_many_to_many_objects(self): 
     
    14891549    return man 
    14901550 
    1491 def manipulator_init(opts, add, change, self, obj_key=None): 
     1551def manipulator_init(opts, add, change, self, obj_key=None, follow=None): 
     1552    self.follow = opts.get_follow(follow)    
     1553     
    14921554    if change: 
    14931555        assert obj_key is not None, "ChangeManipulator.__init__() must be passed obj_key parameter." 
     
    15131575                raise 
    15141576    self.fields = [] 
     1577 
    15151578    for f in opts.fields + opts.many_to_many: 
    1516         if f.editable and not (f.primary_key and change) and (not f.rel or not f.rel.edit_inline): 
     1579        if self.follow.get(f.name, False):    
     1580        # if f.editable and not (f.primary_key and change) and (not f.rel or not f.rel.edit_inline): 
    15171581            self.fields.extend(f.get_manipulator_fields(opts, self, change)) 
    15181582 
    15191583    # Add fields for related objects. 
    1520     for obj in opts.get_inline_related_objects_wrapped(): 
    1521         if change: 
    1522             count = getattr(self.original_object, 'get_%s_count' % opts.get_rel_object_method_name(obj.opts, obj.field))() 
    1523             count += obj.field.rel.num_extra_on_change 
    1524             if obj.field.rel.min_num_in_admin: 
    1525                 count = max(count, obj.field.rel.min_num_in_admin) 
    1526             if obj.field.rel.max_num_in_admin: 
    1527                 count = min(count, obj.field.rel.max_num_in_admin) 
    1528         else: 
    1529             count = obj.field.rel.num_in_admin 
    1530         for f in obj.opts.fields + obj.opts.many_to_many: 
    1531             if f.editable and f != obj.field : 
    1532                 for i in range(count): 
    1533                     self.fields.extend(f.get_manipulator_fields(obj.opts, self, change, name_prefix='%s.%d.' % (obj.opts.object_name.lower(), i), rel=True)) 
     1584    for f in opts.get_all_related_objects_wrapped(): 
     1585        if self.follow.get(f.name, False): 
     1586            fol = self.follow[f.name] 
     1587            self.fields.extend(f.get_manipulator_fields(opts, self, change, fol)) 
     1588 
     1589   # for obj in opts.get_inline_related_objects_wrapped(): 
     1590   #     if change: 
     1591   #         count = getattr(self.original_object, 'get_%s_count' % opts.get_rel_object_method_name(obj.opts, obj.field))() 
     1592   #         count += obj.field.rel.num_extra_on_change 
     1593   #         if obj.field.rel.min_num_in_admin: 
     1594   #             count = max(count, obj.field.rel.min_num_in_admin) 
     1595   #         if obj.field.rel.max_num_in_admin: 
     1596   #             count = min(count, obj.field.rel.max_num_in_admin) 
     1597   #     else: 
     1598   #         count = obj.field.rel.num_in_admin 
     1599   #     for f in obj.opts.fields + obj.opts.many_to_many: 
     1600   #         if f.editable and f != obj.field : 
     1601   #             for i in range(count): 
     1602   #                self.fields.extend(f.get_manipulator_fields(obj.opts, self, change, name_prefix='%s.%d.' % (obj.opts.object_name.lower(), i), rel=True)) 
    15341603 
    15351604    # Add field for ordering. 
     
    15411610    params = {} 
    15421611    for f in opts.fields: 
     1612        auto_now_add = change and getattr(f, 'auto_now_add', False) 
     1613        if self.follow.get(f.name, None) and not auto_now_add: 
     1614            param = f.get_manipulator_new_data(new_data) 
     1615        else: 
     1616            param = getattr(self.original_object, f.column) 
     1617        params[f.column] = param     
     1618     
    15431619        # Fields with auto_now_add are another special case; they should keep 
    15441620        # their original value in the change stage. 
    1545         if change and getattr(f, 'auto_now_add', False): 
    1546             params[f.column] = getattr(self.original_object, f.name) 
    1547         else: 
    1548             params[f.column] = f.get_manipulator_new_data(new_data) 
     1621        #if change and getattr(f, 'auto_now_add', False): 
     1622        #    params[f.column] = getattr(self.original_object, f.name) 
     1623        #else: 
     1624        #    params[f.column] = f.get_manipulator_new_data(new_data) 
    15491625 
    15501626    if change: 
     
    15691645    # Save many-to-many objects. Example: Poll.set_sites() 
    15701646    for f in opts.many_to_many: 
    1571         if not f.rel.edit_inline: 
    1572             was_changed = getattr(new_object, 'set_%s' % f.name)(new_data.getlist(f.name)) 
    1573             if change and was_changed: 
    1574                 self.fields_changed.append(f.verbose_name) 
    1575  
     1647        if self.follow.get(f.name, None): 
     1648            if not f.rel.edit_inline: 
     1649                was_changed = getattr(new_object, 'set_%s' % f.name)(new_data.getlist(f.name)) 
     1650                if change and was_changed: 
     1651                    self.fields_changed.append(f.verbose_name) 
     1652 
     1653    expanded_data = DotExpandedDict(new_data.data) 
    15761654    # Save many-to-one objects. Example: Add the Choice objects for a Poll. 
    1577     for rel_opts, rel_field in opts.get_inline_related_objects(): 
     1655    for related in opts.get_all_related_objects_wrapped(): 
    15781656        # Create obj_list, which is a DotExpandedDict such as this: 
    15791657        # [('0', {'id': ['940'], 'choice': ['This is the first choice']}), 
    15801658        #  ('1', {'id': ['941'], 'choice': ['This is the second choice']}), 
    15811659        #  ('2', {'id': [''], 'choice': ['']})] 
    1582         obj_list = DotExpandedDict(new_data.data)[rel_opts.object_name.lower()].items() 
    1583         obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0]))) 
    1584         params = {} 
    1585  
    1586         # For each related item... 
    1587         for _, rel_new_data in obj_list: 
    1588  
    1589             # Keep track of which core=True fields were provided. 
    1590             # If all core fields were given, the related object will be saved. 
    1591             # If none of the core fields were given, the object will be deleted. 
    1592             # If some, but not all, of the fields were given, the validator would 
    1593             # have caught that. 
    1594             all_cores_given, all_cores_blank = True, True 
    1595  
    1596             # Get a reference to the old object. We'll use it to compare the 
    1597             # old to the new, to see which fields have changed. 
    1598             if change: 
     1660        child_follow = self.follow.get(related.name, None) 
     1661                 
     1662        if child_follow: 
     1663            obj_list = expanded_data[related.var_name].items() 
     1664            obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0]))) 
     1665            params = {} 
     1666 
     1667 
     1668            # For each related item... 
     1669            for _, rel_new_data in obj_list: 
     1670 
     1671                # Keep track of which core=True fields were provided. 
     1672                # If all core fields were given, the related object will be saved. 
     1673                # If none of the core fields were given, the object will be deleted. 
     1674                # If some, but not all, of the fields were given, the validator would 
     1675                # have caught that. 
     1676                all_cores_given, all_cores_blank = True, True 
     1677 
     1678                # Get a reference to the old object. We'll use it to compare the 
     1679                # old to the new, to see which fields have changed. 
    15991680                old_rel_obj = None 
    1600                 if rel_new_data[rel_opts.pk.name][0]: 
    1601                     try: 
    1602                         old_rel_obj = getattr(self.original_object, 'get_%s' % opts.get_rel_object_method_name(rel_opts, rel_field))(**{'%s__exact' % rel_opts.pk.name: rel_new_data[rel_opts.pk.name][0]}) 
    1603                     except ObjectDoesNotExist: 
    1604                         pass 
    1605  
    1606             for f in rel_opts.fields: 
    1607                 if f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) in (None, ''): 
    1608                     all_cores_given = False 
    1609                 elif f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) not in (None, ''): 
    1610                     all_cores_blank = False 
    1611                 # If this field isn't editable, give it the same value it had 
    1612                 # previously, according to the given ID. If the ID wasn't 
    1613                 # given, use a default value. FileFields are also a special 
    1614                 # case, because they'll be dealt with later. 
    1615                 if change and (isinstance(f, FileField) or not f.editable): 
    1616                     if rel_new_data.get(rel_opts.pk.name, False) and rel_new_data[rel_opts.pk.name][0]: 
    1617                         params[f.column] = getattr(old_rel_obj, f.column) 
     1681                if change: 
     1682                    if rel_new_data[related.opts.pk.name][0]: 
     1683                        try: 
     1684                            old_rel_obj = getattr(self.original_object, 'get_%s' % opts.get_rel_object_method_name(related.opts, related.field))(**{'%s__exact' % related.opts.pk.name: rel_new_data[related.opts.pk.name][0]}) 
     1685                        except ObjectDoesNotExist: 
     1686                            pass 
     1687 
     1688                for f in related.opts.fields: 
     1689                    if f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) in (None, ''): 
     1690                        all_cores_given = False 
     1691                    elif f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) not in (None, ''): 
     1692                        all_cores_blank = False 
     1693                    # If this field isn't editable, give it the same value it had 
     1694                    # previously, according to the given ID. If the ID wasn't 
     1695                    # given, use a default value. FileFields are also a special 
     1696                    # case, because they'll be dealt with later. 
     1697                     
     1698                    if f == related.field: 
     1699                        param = getattr(new_object, related.field.rel.field_name) 
     1700                    elif add and isinstance(f, AutoField): 
     1701                        param = None 
     1702                    elif change and (isinstance(f, FileField) or not child_follow.get(f.name, None)): 
     1703                        if old_rel_obj: 
     1704                            param = getattr(old_rel_obj, f.column) 
     1705                        else: 
     1706                            param = f.get_default() 
    16181707                    else: 
    1619                         params[f.column] = f.get_default() 
    1620                 elif f == rel_field: 
    1621                     params[f.column] = getattr(new_object, rel_field.rel.field_name) 
    1622                 elif add and isinstance(f, AutoField): 
    1623                     params[f.column] = None 
    1624                 else: 
    1625                     params[f.column] = f.get_manipulator_new_data(rel_new_data, rel=True) 
    1626                 # Related links are a special case, because we have to 
    1627                 # manually set the "content_type_id" and "object_id" fields. 
    1628                 if opts.has_related_links and rel_opts.module_name == 'relatedlinks': 
    1629                     contenttypes_mod = get_module('core', 'contenttypes') 
    1630                     params['content_type_id'] = contenttypes_mod.get_object(package__label__exact=opts.app_label, python_module_name__exact=opts.module_name).id 
    1631                     params['object_id'] = new_object.id 
    1632  
    1633             # Create the related item. 
    1634             new_rel_obj = rel_opts.get_model_module().Klass(**params) 
    1635  
    1636             # If all the core fields were provided (non-empty), save the item. 
    1637             if all_cores_given: 
    1638                 new_rel_obj.save() 
    1639  
    1640                 # Save any uploaded files. 
    1641                 for f in rel_opts.fields: 
    1642                     if isinstance(f, FileField) and rel_new_data.get(f.name, False): 
    1643                         f.save_file(rel_new_data, new_rel_obj, change and old_rel_obj or None, change, rel=True) 
    1644  
    1645                 # Calculate whether any fields have changed. 
    1646                 if change: 
    1647                     if not old_rel_obj: # This object didn't exist before. 
    1648                         self.fields_added.append('%s "%r"' % (rel_opts.verbose_name, new_rel_obj)) 
    1649                     else: 
    1650                         for f in rel_opts.fields: 
    1651                             if not f.primary_key and f != rel_field and str(getattr(old_rel_obj, f.column)) != str(getattr(new_rel_obj, f.column)): 
    1652                                 self.fields_changed.append('%s for %s "%r"' % (f.verbose_name, rel_opts.verbose_name, new_rel_obj)) 
    1653  
    1654                 # Save many-to-many objects. 
    1655                 for f in rel_opts.many_to_many: 
    1656                     if not f.rel.edit_inline: 
    1657                         was_changed = getattr(new_rel_obj, 'set_%s' % f.name)(rel_new_data[f.name]) 
    1658                         if change and was_changed: 
    1659                             self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, rel_opts.verbose_name, new_rel_obj)) 
    1660  
    1661             # If, in the change stage, all of the core fields were blank and 
    1662             # the primary key (ID) was provided, delete the item. 
    1663             if change and all_cores_blank and rel_new_data.has_key(rel_opts.pk.name) and rel_new_data[rel_opts.pk.name][0]: 
    1664                 new_rel_obj.delete() 
    1665                 self.fields_deleted.append('%s "%r"' % (rel_opts.verbose_name, old_rel_obj)) 
     1708                        param = f.get_manipulator_new_data(rel_new_data, rel=True) 
     1709                     
     1710                    if param: 
     1711                       params[f.column] = param 
     1712                     
     1713 
     1714                    # Related links are a special case, because we have to 
     1715                    # manually set the "content_type_id" and "object_id" fields. 
     1716                    if opts.has_related_links and related.opts.module_name == 'relatedlinks': 
     1717                        contenttypes_mod = get_module('core', 'contenttypes') 
     1718                        params['content_type_id'] = contenttypes_mod.get_object(package__label__exact=opts.app_label, python_module_name__exact=opts.module_name).id 
     1719                        params['object_id'] = new_object.id 
     1720 
     1721                # Create the related item. 
     1722                new_rel_obj = related.opts.get_model_module().Klass(**params) 
     1723     
     1724                 
     1725 
     1726                # If all the core fields were provided (non-empty), save the item. 
     1727                if all_cores_given: 
     1728                    new_rel_obj.save() 
     1729 
     1730                    # Save any uploaded files. 
     1731                    for f in related.opts.fields: 
     1732                        if child_follow.get(f.name, None): 
     1733                            if isinstance(f, FileField) and rel_new_data.get(f.name, False): 
     1734                                f.save_file(rel_new_data, new_rel_obj, change and old_rel_obj or None, change, rel=True) 
     1735 
     1736                    # Calculate whether any fields have changed. 
     1737                    if change: 
     1738                        if not old_rel_obj: # This object didn't exist before. 
     1739                            self.fields_added.append('%s "%r"' % (related.opts.verbose_name, new_rel_obj)) 
     1740                        else: 
     1741                            for f in related.opts.fields: 
     1742                                if not f.primary_key and f != related.field and str(getattr(old_rel_obj, f.column)) != str(getattr(new_rel_obj, f.column)): 
     1743                                    self.fields_changed.append('%s for %s "%r"' % (f.verbose_name, rel_opts.verbose_name, new_rel_obj)) 
     1744 
     1745                    # Save many-to-many objects. 
     1746                    for f in related.opts.many_to_many: 
     1747                        if child_follow.get(f.name, None) and not f.rel.edit_inline: 
     1748                            was_changed = getattr(new_rel_obj, 'set_%s' % f.name)(rel_new_data[f.name]) 
     1749                            if change and was_changed: 
     1750                                self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, rel_opts.verbose_name, new_rel_obj)) 
     1751 
     1752                # If, in the change stage, all of the core fields were blank and 
     1753                # the primary key (ID) was provided, delete the item. 
     1754                if change and all_cores_blank and old_rel_obj: 
     1755                    new_rel_obj.delete() 
     1756                    self.fields_deleted.append('%s "%r"' % (related.opts.verbose_name, old_rel_obj)) 
     1757 
    16661758 
    16671759    # Save the order, if applicable. 
     
    16781770     new_data = {} 
    16791771     obj = change and self.original_object or None 
    1680      for f in opts.get_data_holders(): 
     1772     for f in opts.get_data_holders(self.follow): 
    16811773            new_data.update(f.flatten_data(obj)) 
    16821774     return new_data 
  • django/branches/new-admin/django/views/generic/create_update.py

    r741 r773  
    6969                  slug_field=None, template_name=None, template_loader=template_loader, 
    7070                  extra_lookup_kwargs={}, extra_context={}, post_save_redirect=None,  
    71                   login_required=False): 
     71                  login_required=False, follow=None): 
    7272    """ 
    7373    Generic object-update function. 
     
    9999        raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs)) 
    100100     
    101     manipulator = mod.ChangeManipulator(object.id
     101    manipulator = mod.ChangeManipulator(object.id, follow=follow
    102102     
    103103    if request.POST: 
    104104        new_data = request.POST.copy() 
    105105        errors = manipulator.get_validation_errors(new_data) 
     106        manipulator.do_html2python(new_data) 
    106107        if not errors: 
    107             manipulator.do_html2python(new_data) 
    108108            manipulator.save(new_data) 
    109109             
     
    121121        errors = {} 
    122122        # This makes sure the form acurate represents the fields of the place. 
    123         new_data = object.__dict__ 
     123        new_data = manipulator.flatten_data() 
    124124     
    125125    form = formfields.FormWrapper(manipulator, new_data, errors) 
  • django/branches/new-admin/docs/outputting_pdf.txt

    r765 r773  
    88 
    99The advantage of generating PDF files dynamically is that you can create 
    10 customzed PDFs for different purposes -- say, for different users or different 
     10customized PDFs for different purposes -- say, for different users or different 
    1111pieces of content. 
    1212 
  • django/branches/new-admin/docs/templates_python.txt

    r631 r773  
    268268    from django.core.template import Context 
    269269    import datetime 
    270     class TimeContext(template.Context): 
     270    class TimeContext(Context): 
    271271        def __init__(self, *args, **kwargs): 
    272272            Context.__init__(self, *args, **kwargs)