【问题标题】:Django: structuring a complex relationship intended for use with built-in admin siteDjango:构建用于内置管理站点的复杂关系
【发布时间】:2009-12-24 05:01:22
【问题描述】:

我有一个相当复杂的关系,我正在尝试与 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)

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

如果我将 EmployeeInline 设为 DepartmentAdmin 的内联(而不是在 GroupAdmin 中使用 DepartmentInline),那么情况会更糟,因为不可能有不属于某个组的 Employee。

鉴于我对关系的描述,我是否错过了 Django ORM 的某些部分,它允许我按照“应该”的方式构建这种关系,而不是四处乱窜并试图让事情走到一起?

非常感谢。

【问题讨论】:

    标签: django django-models django-admin


    【解决方案1】:

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

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

    你可以通过一些 ninja 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 不考虑已经选择的选项(然后重新选择它)。

    【讨论】:

      猜你喜欢
      • 2010-09-14
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      相关资源
      最近更新 更多