| 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 |
|---|
| 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)) |
|---|
| 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. |
|---|
| 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() |
|---|
| 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 | |
|---|