method - get_context_data django
¿Cómo mostrar elementos relacionados usando DeleteView en Django? (3)
Estoy haciendo una vista para eliminar (usando la vista genérica DeleteView de Django) una instancia de un modelo, pero en cascada y elimina las instancias de otros modelos:
url(r''^person/(?P<pk>/d+)/delete/$'', login_required(DeleteView.as_view(model=Person, success_url=''/person/'', template_name=''delete.html'')), name=''person_delete''),
Lo que quiero hacer es mostrar la lista de elementos relacionados que se van a eliminar, como lo hace la interfaz de administración, como:
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
Actualización: desde Django 1.9+ NestedObject se debe importar desde django.contrib.admin.util s
from django.contrib.admin.utils import NestedObjects
Puede usar la clase Collector
usa Django para determinar qué objetos eliminar en la cascada. Instálelo y luego invoque la collect
en él pasando los objetos que desea eliminar. Espera una lista o un conjunto de consultas, por lo que si solo tiene un objeto, simplemente colóquelo dentro de una lista:
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
devuelve un generador, por lo que solo puede usarlo dentro del contexto de un bucle. Si prefiere una estructura de datos real que pueda manipular, el paquete admin
contrib tiene una subclase de Collector
llamada NestedObjects
, que funciona de la misma manera, pero tiene un método nested
que devuelve una lista jerárquica:
from django.contrib.admin.utils import NestedObjects
collector = NestedObjects(using=''default'') # or specific database
collector.collect([some_instance])
to_delete = collector.nested()
Actualizado: desde Django 1.9, django.contrib.admin.util cambió su nombre a django.contrib.admin.utils
Utilizo una modifcación reducida de get_deleted_objects () del administrador y la uso para extender mi contexto en get_context en la vista de eliminación:
definir en algún lugar
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
entonces en tus puntos de vista
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
Ahora puedes usarlos en tu plantilla.
<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>