Как показать связанные элементы с помощью DeleteView в Django?
Я делаю вид, чтобы удалить (используя общий вид DeleteView из Django) экземпляр из модели, но он каскадирует и удаляет экземпляры из других моделей:
url(r'^person/(?P<pk>\d+)/delete/$', login_required(DeleteView.as_view(model=Person, success_url='/person/', template_name='delete.html')), name='person_delete'),
Что я хочу сделать, так это показать список связанных элементов, которые будут удалены, как это делает интерфейс администратора, например:
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
Ответы
Ответ 1
Вы можете использовать Collector
класс, используемый Django для определения того, какие объекты нужно удалить в каскаде. Выполните его, а затем вызовите collect
, передав объекты, которые вы собираетесь удалить. Он ожидает список или набор запросов, поэтому, если у вас есть только один объект, просто введите внутри списка:
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
возвращает генератор, поэтому вы можете использовать его только в контексте цикла. Если вы предпочитаете фактическую структуру данных, которую вы можете манипулировать, пакет admin
contrib имеет подкласс Collector
, называемый NestedObjects
, который работает одинаково, но имеет метод nested
, который возвращает иерархический список:
from django.contrib.admin.utils import NestedObjects
collector = NestedObjects(using='default') # or specific database
collector.collect([some_instance])
to_delete = collector.nested()
Обновлено: Поскольку Django 1.9, django.contrib.admin.util был переименован в django.contrib.admin.utils
Ответ 2
Обновление: из Django 1.9+ NestedObject следует импортировать из django.contrib.admin.util s
from django.contrib.admin.utils import NestedObjects
Ответ 3
Я использую модификацию вырезания get_deleted_objects() из admin
и использовать его для расширения моего контекста в get_context в представлении удаления:
определить где-нибудь
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
, то в ваших представлениях
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
теперь вы можете использовать их в своем шаблоне
<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>
Большинство из них просто копируют/вставляют/редактируют/удаляют нежелательные из django admin