我有一个相当复杂的关系,我正在尝试使用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的某些部分,这将允许我按照“应该”的方式构建这种关系,而不是黑客攻击并试图让事情融合在一起?
非常感谢。
答案 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没有考虑已经选择的选项(然后重新选择它)。