Django: структурирование сложных отношений, предназначенных для использования со встроенным админ-сайтом - PullRequest
0 голосов
/ 24 декабря 2009

У меня довольно сложные отношения, которые я пытаюсь заставить работать с сайтом администратора 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)

Проблема в том, что в поле выбора отдела на странице «Сотрудники» должны отображаться все отделы, поскольку группа еще не установлена. Я попытался исправить это, создав EmployeeInline для страницы GroupAdmin, но не стоит иметь более 500 сотрудников на встроенной странице без разбивки на страницы. Я должен иметь возможность использовать страницу models.ModelAdmin для сотрудников (если только нет способа искать, сортировать, сворачивать и выполнять действия на встроенных линиях).

Если я сделаю EmployeeInline встроенным в DepartmentAdmin (вместо DepartmentInline в GroupAdmin), то все будет еще хуже, поскольку невозможно иметь Employee, не принадлежащего к группе.

Учитывая мое описание отношений, я упускаю какую-то часть ORM Django, которая позволит мне структурировать эти отношения так, как они «должны быть», вместо того, чтобы взламывать и пытаться объединить вещи? *

Большое спасибо.

1 Ответ

3 голосов
/ 24 декабря 2009

Похоже, что вы хотите, чтобы параметры Департамента были только теми, которые ForeignKey'ed для группы? Стандартный ответ: администратор сайта предназначен только для простых операций 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 не учитывается вариант, который уже был выбран (а затем повторно выбран).

...