Как показать связанные элементы с помощью 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

3 ответов


можно использовать Collector класс Django использует для определения того, какие объекты удалять в каскаде. Создайте его экземпляр, а затем вызовите collect на нем проходят объекты, которые вы намерены удалить. Он ожидает список или queryset, поэтому, если у вас есть только один объект, просто поместите его в список:

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,Джанго.ВНО.администратор.util была переименована в Джанго.ВНО.администратор.utils


Update: из Django 1.9 + NestedObject должен быть импортирован из django.ВНО.администратор.utils

    from django.contrib.admin.utils import NestedObjects

Я использую модификацию сокращения get_deleted_objects () от администратора и используйте его для расширения моего контекста в 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