Django:构建一个旨在与内置管理站点一起使用的复杂关系

时间:2009-12-24 05:01:23

标签: django django-models django-admin

我有一个相当复杂的关系,我正在尝试使用Django管理站点。我花了很多时间试图做到这一点,看起来我似乎没有得到Django模型背后的哲学。

有一个群组列表。每个小组都有多个部门。还有员工。每个员工属于一个组,但是一些员工也属于组内的单个部门。 (有些员工可能只属于一个集团但没有部门,但没有员工只属于部门。)

以下是我目前所拥有的简化版本:

class Group:
  name = models.CharField(max_length=128)

class Department
  group = models.ForeignKey(Group)

class Employee
  department = models.ForeignKey(Department)
  group = models.ForeignKey(Group)

问题在于Employees页面上的Department选择框必须显示所有Departments,因为尚未设置组。我试图通过为GroupAdmin页面创建EmployeeInline来纠正这个问题,但是在非分页内联中拥有500多名员工并不好。我必须能够使用Employees的models.ModelAdmin页面(除非有一种方法可以对内联进行搜索,排序,折叠和执行操作)。

如果我使EmployeeInline成为DepartmentAdmin的内联(而不是在GroupAdmin中有一个DepartmentInline),那么事情就更糟了,因为不可能有一个不属于Group的Employee。

鉴于我对这些关系的描述,我是否错过了Django ORM的某些部分,这将允许我按照“应该”的方式构建这种关系,而不是黑客攻击并试图让事情融合在一起?

非常感谢。

1 个答案:

答案 0 :(得分:3)

听起来你想要的部门选项只是那些是ForeignKey'ed Group?标准答案是管理站点仅用于简单的CRUD操作。

但做你应该做的事情很无聊。

你可以通过一些忍者javascript和JSON克服这个限制。

首先,我们需要一个API,让我们知道哪些部门可用于每个组。

def api_departments_from_group(request, group_id):
    departments = Department.objects.filter(group__id=group_id)
    return json(departments)  # Note: serialize, however

一旦API到位,我们可以添加一些javascript来更改部门选择中的<option> ...

$(function() {
    // On page load...
    if ($('#id_group')) {
        // Trap when the group box is changed
        $('#id_group').bind('blur', function() {
            $.getJSON('/api/get-departments/' + $('#id_group').val() + '/', function(data) {
                // Clear existing options
                $('#id_department').children().remove();
                // Parse JSON and turn into <option> tags
                $.each(data, function(i, item) {
                    $('#id_department').append('<option>' + item.name + '</option>');
                });
            });
        });
    }
});

将其保存到admin-ninja.js。然后你可以把它包含在管理模型本身......

class EmployeeAdmin(models.ModelAdmin):

    # ...

    class Media:
        js = ('/media/admin-ninja.js',)

是的,所以我没有测试过这一点,但你可以得到一些想法。此外,我没有想到任何东西,例如javascript没有考虑已经选择的选项(然后重新选择它)。