如何在删除Django中的foreignkey对象之前传输所有子对象?

时间:2013-03-26 12:11:53

标签: django foreign-keys

我知道on_delete选项可以在删除现有外键时将另一个foreignkey对象设置为替换。但我的客户想要的是这个流程:

  1. 点击删除按钮(从管理员的更改页面或列表页面)
  2. 如果此对象具有子元素,则显示一个列出所有可用外键对象的选择框。所选对象将用于填充这些子对象的外键。
  3. 将子对象转移到另一个外键后,提供确认删除按钮。
  4. 有没有人知道如何在Django管理员上执行此操作?在删除例如用户时,Wordpress具有类似的功能。它提供了将文章转移给其他用户的选项。

2 个答案:

答案 0 :(得分:0)

您必须编写自己的视图才能获得所描述的流程。它不能在Django Admin中完成。

Django Admin本身就是一个应用程序,而不是用于创建自己的应用程序的框架或库。

答案 1 :(得分:0)

items.models.py

from django.db import models


class Slugged(models.Model):
    title = models.CharField(max_length=500)
    slug = models.CharField(max_length=2000, blank=True, null=True)

    class Meta:
        abstract = True

    def __unicode__(self):
        return self.title


class Item(Slugged):
    # SET_NULL for safety
    category = models.ForeignKey("Category", blank=True, null=True, on_delete=models.SET_NULL)


class Category(Slugged):
    pass

items.views.py

from django.views import generic
from django.views.generic.edit import FormMixin

from jsonview.decorators import json_view
# this is from @jsocol/django-jsonview but there are other ways to do this

from .models import Item, Category


class CategoryUpdateView(generic.UpdateView):
    model = Category

    def get_context_data(self, **kwargs):
        self.object = super(CategoryUpdateView, self).get_object()
        context = super(CategoryUpdateView, self).get_context_data(**kwargs)
        context['available_fks'] = Category.objects.exclude(pk=self.object.id)      
        context.update(kwargs)
        return super(CategoryUpdateView, self).get_context_data(**kwargs)


class CategoryDeleteView(generic.DeleteView, FormMixin):
    model = Task
    success_url = '/'

    @json_view
    def dispatch(self, *args, **kwargs):
        return super(CategoryDeleteView, self).dispatch(*args, **kwargs)

    def delete(self, request, *args, **kwargs):
        self.object = super(CategoryDeleteView, self).get_object()
        self.object.delete()
        return {'success':True}

    def post(self, request, *args, **kwargs):
        self.object = super(CategoryDeleteView, self).get_object()
        if request.POST.has_key('new_fk'):
            new_fk = get_object_or_404(Category, pk=request.POST['new_fk'])
            for item in self.object.item_set.all():
                item.category = new_fk
                item.save()
        else:
            return {'success': False}
        return self.delete(self, request, *args, **kwargs)

items.templates.items.category_update.html

<form action="" method="post" enctype="multipart/form-data" id="category-delete-form">
    {% csrf_token %}
    {{ form }}
    <select id="new_fk">
        <option value="" >---------</option>
        {% for fk in available_fks %} 
             <option value="{{ fk.if }}"{% if forloop.first %} selected="selected"{% endif %}>{{ fk.title }}</option>
        {% endfor %}
    </select>
    <input type="submit" name="delete_category" value="Delete">
</form>

items.static.items.deleteItem.js

function deleteCategory(deleteUrl, form_id) {
    var $form = $('#' + form_id);
    var new_pk = $form.find('#new_fk').val();
    $.ajax({
        url: deleteUrl,
        type: 'POST',
        data: 'csrfmiddlewaretoken=' + getCookie('csrftoken') + '&new_fk=' + new_fk,
        success: function(data) {
            if (data['success']){
                $form.remove();
                alert('success');
            }
            else {
                alert('FAIL');
            }

        }
    });
}
$('#category-delete-form').on('submit', function () {
    $this = $(this);
    deleteCategory($this.attr('action'), $this.id);
}

@goldhand gist