Exemple #1
0
    def delete_view(self, request, *args, **kwargs):
        """
        Handles deletion
        """
        obj = self.get_object_or_404(request, *args, **kwargs)

        if not self.deletion_allowed(request, obj):
            return self.response_deletion_denied(request, obj)

        form = self.get_deletion_form_instance(request, obj)

        if form.is_valid():
            obj.delete()
            return self.response_delete(request, obj)
        else:
            if not hasattr(obj, '_collected_objects'):
                related_classes(obj)

            collected_objects = [
                (key._meta, len(value))
                for key, value in obj._collected_objects.items()]

            return self.render_delete_confirmation(request, {
                'title': capfirst(_('Delete %s') % force_text(
                    self.model._meta.verbose_name)),
                self.template_object_name: obj,
                'collected_objects': collected_objects,
                'form': form,
            })
Exemple #2
0
    def delete_view(self, request, *args, **kwargs):
        """
        Handles deletion
        """
        obj = self.get_object_or_404(request, *args, **kwargs)

        if not self.deletion_allowed(request, obj):
            return self.response_deletion_denied(request, obj)

        if request.method == 'POST':
            obj.delete()
            return self.response_delete(request, obj)
        else:
            if not hasattr(obj, '_collected_objects'):
                related_classes(obj)

            collected_objects = [
                (key._meta, len(value))
                for key, value in obj._collected_objects.items()
            ]

            return self.render_delete_confirmation(
                request, {
                    'title':
                    _('Delete %s') %
                    force_unicode(self.model._meta.verbose_name),
                    self.template_object_name:
                    obj,
                    'collected_objects':
                    collected_objects,
                })
Exemple #3
0
    def delete_view(self, request, *args, **kwargs):
        """
        Handles deletion
        """
        obj = self.get_object_or_404(request, *args, **kwargs)

        if not self.deletion_allowed(request, obj):
            return self.response_deletion_denied(request, obj)

        if request.method == 'POST':
            obj.delete()
            return self.response_delete(request, obj)
        else:
            if not hasattr(obj, '_collected_objects'):
                related_classes(obj)

            collected_objects = [(key._meta, len(value)) for key, value
                in obj._collected_objects.items()]

            return self.render_delete_confirmation(request, {
                'title': _('Delete %s') % force_unicode(
                    self.model._meta.verbose_name),
                self.template_object_name: obj,
                'collected_objects': collected_objects,
                })
Exemple #4
0
    def delete_view(self, request, *args, **kwargs):
        """
        Handles deletion
        """
        obj = self.get_object_or_404(request, *args, **kwargs)

        if not self.deletion_allowed(request, obj):
            return self.response_deletion_denied(request, obj)

        form = self.get_deletion_form_instance(request, obj)

        if form.is_valid():
            obj.delete()
            return self.response_delete(request, obj)
        else:
            if not hasattr(obj, '_collected_objects'):
                related_classes(obj)

            collected_objects = [
                (key._meta, len(value))
                for key, value in obj._collected_objects.items()]

            return self.render_delete_confirmation(request, {
                'title': capfirst(_('Delete %s') % force_text(
                    self.model._meta.verbose_name)),
                self.template_object_name: obj,
                'collected_objects': collected_objects,
                'form': form,
            })
Exemple #5
0
    def deletion_allowed_if_only(self, request, instance, classes):
        """
        Helper which is most useful when used inside ``deletion_allowed``

        Allows the deletion if the deletion cascade only contains
        objects from the given classes. Adds a message if deletion is
        not allowed containing details which classes are preventing
        deletion.

        Example::

            def deletion_allowed(self, request, instance):
                return self.deletion_allowed_if_only(request, instance, [
                    Ticket, TicketUpdate])
        """
        related = set(related_classes(instance))

        related.discard(self.model)
        for class_ in classes:
            related.discard(class_)

        if len(related):
            pretty_classes = [
                unicode(class_._meta.verbose_name_plural) for class_ in related
            ]
            if len(pretty_classes) > 1:
                pretty_classes = u''.join((u', '.join(pretty_classes[:-1]),
                                           _(' and '), pretty_classes[-1]))
            else:
                pretty_classes = pretty_classes[-1]

            self.add_message(request, 'deletion_denied_related',
                             {'pretty_classes': pretty_classes})

        return not len(related)
Exemple #6
0
    def deletion_allowed_if_only(self, request, instance, classes):
        """
        Helper which is most useful when used inside ``deletion_allowed``

        Allows the deletion if the deletion cascade only contains
        objects from the given classes. Adds a message if deletion is
        not allowed containing details which classes are preventing
        deletion.

        Example::

            def deletion_allowed(self, request, instance):
                return self.deletion_allowed_if_only(request, instance, [
                    Ticket, TicketUpdate])
        """
        related = set(related_classes(instance))

        related.discard(self.model)
        for class_ in classes:
            related.discard(class_)

        if len(related):
            pretty_classes = [unicode(class_._meta.verbose_name_plural) for class_ in related]
            if len(pretty_classes) > 1:
                pretty_classes = u''.join((
                    u', '.join(pretty_classes[:-1]),
                    _(' and '),
                    pretty_classes[-1]))
            else:
                pretty_classes = pretty_classes[-1]

            self.add_message(request, 'deletion_denied_related', {'pretty_classes' : pretty_classes })

        return not len(related)
Exemple #7
0
    def save_formset_deletion_allowed_if_only(
        self, request, form, formset, change, classes
    ):
        """
        Helper which has is most useful when used inside ``save_formsets``

        To use this method properly, your model has to inherit from
        ``towel.deletion.Model``. This is NOT enforced. If you ignore this, the
        instances will be deleted by ``formset.save()`` as is the default with
        Django.

        Example::

            def save_formsets(self, requset, form, formsets, change):
                # Allow deleting states when the cascade includes
                # ``SomeModel`` instances only.
                self.save_formset_deletion_allowed_if_only(
                    request, form, formsets['states'], change, [SomeModel])

                # No special handling for other formsets
                self.save_formset(request, form, formsets['otherformset'],
                    change=change)

        """
        with deletion.protect():
            self.save_formset(request, form, formset, change)

        for instance in formset.deleted_objects:
            related = set(related_classes(instance))

            related.discard(instance.__class__)
            for class_ in classes:
                related.discard(class_)

            if len(related):
                pretty_classes = [
                    force_text(class_._meta.verbose_name_plural) for class_ in related
                ]

                if len(pretty_classes) > 1:
                    pretty_classes = "".join(
                        (
                            ", ".join(pretty_classes[:-1]),
                            ugettext(" and "),
                            pretty_classes[-1],
                        )
                    )
                else:
                    pretty_classes = pretty_classes[-1]

                self.add_message(
                    request,
                    "deletion_denied_related",
                    {"pretty_classes": pretty_classes},
                )
            else:
                instance.delete()
Exemple #8
0
    def save_formset_deletion_allowed_if_only(self, request, form, formset,
                                              change, classes):
        """
        Helper which has is most useful when used inside ``save_formsets``

        To use this method properly, your model has to inherit from
        ``towel.deletion.Model``. This is NOT enforced. If you ignore this, the
        instances will be deleted by ``formset.save()`` as is the default with
        Django.

        Example::

            def save_formsets(self, requset, form, formsets, change):
                # Allow deleting states when the cascade includes
                # ``SomeModel`` instances only.
                self.save_formset_deletion_allowed_if_only(
                    request, form, formsets['states'], change, [SomeModel])

                # No special handling for other formsets
                self.save_formset(request, form, formsets['otherformset'], change)

        """
        with deletion.protect():
            self.save_formset(request, form, formset, change)

        for instance in formset.deleted_objects:
            related = set(related_classes(instance))

            related.discard(instance.__class__)
            for class_ in classes:
                related.discard(class_)

            if len(related):
                pretty_classes = [
                    unicode(class_._meta.verbose_name_plural)
                    for class_ in related
                ]
                if len(pretty_classes) > 1:
                    pretty_classes = u''.join((u', '.join(pretty_classes[:-1]),
                                               _(' and '), pretty_classes[-1]))
                else:
                    pretty_classes = pretty_classes[-1]

                messages.error(
                    request,
                    _('Deletion of %(instance)s not allowed: <small>There are %(classes)s related to this object.</small>'
                      ) % {
                          'instance': instance,
                          'classes': pretty_classes,
                      })
            else:
                instance.delete()
Exemple #9
0
    def save_formset_deletion_allowed_if_only(self, request, form, formset,
                                              change, classes):
        """
        Helper which has is most useful when used inside ``save_formsets``

        To use this method properly, your model has to inherit from
        ``towel.deletion.Model``. This is NOT enforced. If you ignore this, the
        instances will be deleted by ``formset.save()`` as is the default with
        Django.

        Example::

            def save_formsets(self, requset, form, formsets, change):
                # Allow deleting states when the cascade includes
                # ``SomeModel`` instances only.
                self.save_formset_deletion_allowed_if_only(
                    request, form, formsets['states'], change, [SomeModel])

                # No special handling for other formsets
                self.save_formset(request, form, formsets['otherformset'],
                    change=change)

        """
        with deletion.protect():
            self.save_formset(request, form, formset, change)

        for instance in formset.deleted_objects:
            related = set(related_classes(instance))

            related.discard(instance.__class__)
            for class_ in classes:
                related.discard(class_)

            if len(related):
                pretty_classes = [
                    force_text(class_._meta.verbose_name_plural)
                    for class_ in related]

                if len(pretty_classes) > 1:
                    pretty_classes = ''.join((
                        ', '.join(pretty_classes[:-1]),
                        ugettext(' and '),
                        pretty_classes[-1],
                    ))
                else:
                    pretty_classes = pretty_classes[-1]

                self.add_message(request, 'deletion_denied_related', {
                    'pretty_classes': pretty_classes})
            else:
                instance.delete()
Exemple #10
0
    def test_related_classes(self):
        """Test the functionality of towel.utils.related_classes"""
        person = Person.objects.create(
            family_name="Muster",
            given_name="Hans",
        )
        EmailAddress.objects.create(
            person=person,
            email="*****@*****.**",
        )

        self.assertEqual(
            set(related_classes(person)),
            set((Person, EmailAddress)),
        )
Exemple #11
0
    def test_related_classes(self):
        """Test the functionality of towel.utils.related_classes"""
        person = Person.objects.create(
            family_name='Muster',
            given_name='Hans',
        )
        EmailAddress.objects.create(
            person=person,
            email='*****@*****.**',
        )

        self.assertEqual(
            set(related_classes(person)),
            set((Person, EmailAddress)),
        )
Exemple #12
0
    def save_formset_deletion_allowed_if_only(self, request, form, formset, change, classes):
        """
        Helper which has is most useful when used inside ``save_formsets``

        To use this method properly, your model has to inherit from
        ``towel.deletion.Model``. This is NOT enforced. If you ignore this, the
        instances will be deleted by ``formset.save()`` as is the default with
        Django.

        Example::

            def save_formsets(self, requset, form, formsets, change):
                # Allow deleting states when the cascade includes
                # ``SomeModel`` instances only.
                self.save_formset_deletion_allowed_if_only(
                    request, form, formsets['states'], change, [SomeModel])

                # No special handling for other formsets
                self.save_formset(request, form, formsets['otherformset'], change)

        """
        with deletion.protect():
            self.save_formset(request, form, formset, change)

        for instance in formset.deleted_objects:
            related = set(related_classes(instance))

            related.discard(instance.__class__)
            for class_ in classes:
                related.discard(class_)

            if len(related):
                pretty_classes = [unicode(class_._meta.verbose_name_plural) for class_ in related]
                if len(pretty_classes) > 1:
                    pretty_classes = u''.join((
                        u', '.join(pretty_classes[:-1]),
                        _(' and '),
                        pretty_classes[-1]))
                else:
                    pretty_classes = pretty_classes[-1]

                messages.error(request, _('Deletion of %(instance)s not allowed: <small>There are %(classes)s related to this object.</small>') % {
                    'instance': instance,
                    'classes': pretty_classes,
                    })
            else:
                instance.delete()
Exemple #13
0
    def deletion_allowed_if_only(self, request, instance, classes):
        """
        Helper which is most useful when used inside ``deletion_allowed``

        Allows the deletion if the deletion cascade only contains
        objects from the given classes. Adds a message if deletion is
        not allowed containing details which classes are preventing
        deletion.

        Example::

            def deletion_allowed(self, request, instance):
                return self.deletion_allowed_if_only(request, instance, [
                    Ticket, TicketUpdate])
        """
        related = set(related_classes(instance))

        related.discard(self.model)
        for class_ in classes:
            related.discard(class_)

        if len(related):
            pretty_classes = [
                force_text(class_._meta.verbose_name_plural) for class_ in related
            ]

            if len(pretty_classes) > 1:
                pretty_classes = "".join(
                    (
                        ", ".join("%s" % cls for cls in pretty_classes[:-1]),
                        ugettext(" and "),
                        "%s" % pretty_classes[-1],
                    )
                )
            else:
                pretty_classes = pretty_classes[-1]

            self.add_message(
                request,
                "deletion_denied_related",
                {"pretty_classes": pretty_classes},
                ignore=("deletion_denied",),
            )

        return not len(related)
Exemple #14
0
    def allow_delete_if_only(self, object, related=(), silent=True):
        """
        This helper is most useful when used inside ``allow_delete``. It can
        be used to easily determine whether there are related instances which
        would be deleted as well.

        Returns ``True`` if the classes only belong to the model itself and
        to the classes mentioned in ``related``.
        """
        classes = set(related_classes(object)).difference((self.model, ),
                                                          related)
        if not classes:
            return True
        if not silent:
            messages.error(
                self.request,
                _('Deletion not allowed because of related objects: %s') %
                (', '.join(
                    force_text(cls._meta.verbose_name_plural)
                    for cls in classes), ))
        return False
Exemple #15
0
    def allow_delete_if_only(self, object, related=(), silent=True):
        """
        This helper is most useful when used inside ``allow_delete``. It can
        be used to easily determine whether there are related instances which
        would be deleted as well.

        Returns ``True`` if the classes only belong to the model itself and
        to the classes mentioned in ``related``.
        """
        classes = set(related_classes(object)).difference(
            (self.model,), related)
        if not classes:
            return True
        if not silent:
            messages.error(
                self.request,
                _('Deletion not allowed because of related objects: %s') % (
                    ', '.join(
                        force_text(cls._meta.verbose_name_plural)
                        for cls in classes
                    ),
                )
            )
        return False