¿Cómo mostrar elementos relacionados usando DeleteView en Django?
Frecuentes
Visto 9,580 veces
27
I am doing a view to delete (using the generic view DeleteView from Django) an instance from a model, but it cascades and deletes instances from other models:
url(r'^person/(?P<pk>\d+)/delete/$', login_required(DeleteView.as_view(model=Person, success_url='/person/', template_name='delete.html')), name='person_delete'),
What I want to do is to show the list of related items that are going to be deleted, as the admin interface does, like:
Are you sure you are going to delete Person NAMEOFTHEPERSON?
By deleting it, you are also going to delete:
CLASSNAME1: CLASSOBJECT1 ; CLASSNAME2: CLASSOBJECT2 ; CLASSNAME3: CLASSOBJECT3 ; etc
2 Respuestas
52
Puede utilizar el Collector
class Django uses to determine what objects to delete in the cascade. Instantiate it and then call collect
on it passing the objects you intend to delete. It expects a list or queryset, so if you only have one object, just put in inside a list:
from django.db.models.deletion import Collector
collector = Collector(using='default') # or specific database
collector.collect([some_instance])
for model, instance in collector.instances_with_model():
# do something
instances_with_model
returns a generator, so you can only use it within the context of a loop. If you'd prefer an actual data structure that you can manipulate, the admin
contrib package has a Collector
subclase llamada NestedObjects
, that works the same way, but has a nested
method that returns a hierarchical list:
from django.contrib.admin.utils import NestedObjects
collector = NestedObjects(using='default') # or specific database
collector.collect([some_instance])
to_delete = collector.nested()
Updated: Since Django 1.9, django.contrib.admin.util fue renombrado a django.contrib.admin.utils
Respondido el 19 de diciembre de 17 a las 08:12
7
I use a cutdown modifcation of get_deleted_objects() from the admin and use it to extend my context in get_context in the delete view:
define somewhere
from django.contrib.admin.utils import NestedObjects
from django.utils.text import capfirst
from django.utils.encoding import force_text
def get_deleted_objects(objs):
collector = NestedObjects(using='default')
collector.collect(objs)
#
def format_callback(obj):
opts = obj._meta
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name),
force_text(obj))
return no_edit_link
#
to_delete = collector.nested(format_callback)
protected = [format_callback(obj) for obj in collector.protected]
model_count = {model._meta.verbose_name_plural: len(objs) for model, objs in collector.model_objs.items()}
#
return to_delete, model_count, protected
then in your views
from somewhere import get_deleted_objects
#
class ExampleDelete(DeleteView):
# ...
def get_context_data(self, **kwargs):
#
context = super().get_context_data(**kwargs)
#
deletable_objects, model_count, protected = get_deleted_objects([self.object])
#
context['deletable_objects']=deletable_objects
context['model_count']=dict(model_count).items()
context['protected']=protected
#
return context
now you can use them in your template
<table>
<tr>
<th>Name</th>
<th>Amount</th>
</tr>
{% for model_name, object_count in model_count %}
<tr>
<td>{{ model_name|capfirst }}</td>
<td>{{ object_count }}</td>
</tr>
{% endfor %}
</table>
<p>
<ul>
{{ deletable_objects|unordered_list }}
</ul>
</p>
Most is just copy/paste/edit/delete unwanted from django admin
Respondido el 16 de Septiembre de 16 a las 15:09
get_context should be get_context_data - JRM
This works fine. On a many to many with self referencing, to_delete contains also something like 'From_company-to_company relationship: Company_contractor object (13)'. How to show properly also this kind of relationship? - c susurrador
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas django view cascade or haz tu propia pregunta.
Note that Collector does not resolve many-to-many fields, you need to use NestedObjects to do that. - Emil Stenström