Django:构建用于内置管理站点的复杂关系

发布于 2024-08-16 04:14:15 字数 818 浏览 2 评论 0原文

我有一个相当复杂的关系,我正在尝试与 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 的某些部分,它允许我按照“应该”的方式构建这种关系,而不是四处乱搞并试图将事情整合在一起?

多谢。

I have a fairly complex relationship that I am trying to make work with the Django admin site. I have spent quite some time trying to get this right and it just seems like I am not getting the philosophy behind the Django models.

There is a list of Groups. Each Group has multiple departments. There are also Employees. Each Employee belongs to a single group, but some employees also belong to a single Department within a Group. (Some employees might belong to only a Group but no Department, but no Employee will belong only to a Department).

Here is a simplified version of what I currently have:

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

class Department
  group = models.ForeignKey(Group)

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

The problem with this is that the Department select box on the Employees page must display all Departments, because a group has not yet been set. I tried to rectify this by making an EmployeeInline for the GroupAdmin page, but it is not good to have 500+ employees on a non-paginated inline. I must be able to use the models.ModelAdmin page for Employees (unless there is a way to search, sort, collapse and perform actions on inlines).

If I make EmployeeInline an inline of DepartmentAdmin (instead of having a DepartmentInline in GroupAdmin), then things are even worse, because it is not possible to have an Employee that does not belong to a Group.

Given my description of the relationships, am I missing out on some part of the Django ORM that will allow me to structure this relationship the way it 'should be' instead of hacking around and trying to make things come together?

Thanks a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

反差帅 2024-08-23 04:14:15

听起来您想要的部门选项只是那些通过外键分组的选项?标准答案是管理站点仅用于简单的 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 来更改部门选择上的 ...

$(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 不考虑已经选择的选项(然后重新选择它)。

It sounds like what you want is for the Department options to only be those that are ForeignKey'ed to Group? The standard answer is that the admin site is only for simple CRUD operations.

But doing what you're supposed to do is boring.

You could probably overcome this limitation with some ninja javascript and JSON.

So first of all, we need an API that can let us know which departments are available for each group.

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

Once the API is in place we can add some javascript to change the <option>'s on the department select...

$(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>');
                });
            });
        });
    }
});

Save that to admin-ninja.js. Then you can include it on the admin model itself...

class EmployeeAdmin(models.ModelAdmin):

    # ...

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

Yeah, so I didn't test a drop of this, but you can get some ideas hopefully. Also, I didn't get fancy with anything, for example the javascript doesn't account for an option already already being selected (and then re-select it).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文