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, })
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, })
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, })
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)
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)
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()
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()
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()
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)), )
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)), )
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()
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)
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
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