27

我正在做一个视图来删除(使用来自 Django 的通用视图 DeleteView)模型中的一个实例,但它会级联并从其他模型中删除实例:

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
4

2 回答 2

52

您可以使用CollectorDjango 使用的类来确定要在级联中删除哪些对象。实例化它,然后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返回一个生成器,因此您只能在循环的上下文中使用它。如果您更喜欢可以操作的实际数据结构,admincontrib 包有一个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

于 2012-08-28T15:29:21.473 回答
7

我使用管理员对 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 复制/粘贴/编辑/删除不需要的内容

于 2016-09-16T14:10:15.573 回答