2009-12-16 4 views
1

Я думаю, что мое понимание FK и администратора Django немного ошибочно, поэтому я бы оценил любой ввод того, как моделировать приведенный ниже случай.Django - Проектирование отношений модели - интерфейс администратора и Inline

Во-первых, у нас есть общие объекты Address. Затем у нас есть User, у каждого из которых есть UserProfile. Благодаря этому пользователи принадлежат отделам, а также имеют адреса.

Сами департаменты также могут иметь несколько адресов, а также руководитель отдела. Так что это может быть что-то вроде (это что-то я просто хакерства до сих пор):

class Address(models.Model): 
    street_address = models.CharField(max_length=20) 
    etc... 

class Department(models.Model): 
    name = models.CharField(max_lenght=20) 
    head_of_department = models.OneToOneField(User) 
    address = models.ForeignKey(Address) 

class UserProfile(models.Model): 
    user = models.ForeignKey(User, unique=True) 
    address = models.ForeignKey(Address) 
    department = models.OneToOneField(Department) 

Во всяком случае, во-первых, является то, что правильный способ создания отношений?

И, во-вторых, я хотел бы, чтобы он появился в администраторе, чтобы вы могли редактировать отдел, и на этой странице он имел бы встроенный список всех адресов для редактирования. Я попытался создать класс AddressInline и привязать его как встроенный к отделу.

class AddressInline(admin.TabularInline): 
    model = Address 

class DepartmentAdmin(admin.ModelAdmin): 
    inlines = [AddressInline] 

Однако, когда я пытаюсь показать, что я получаю:

Exception at /admin/people/department/1/ 
<class 'people.models.Address'> has no ForeignKey to <class 'people.models.Department'> 

Приветствия, Victor

+0

Вам нужно использовать 'ManyToManyField' для адреса в классах Департамента и UserProfile. – czarchaic

+0

Celopes: Спасибо, что указали это, вернулись и приняли старые. Я не понимал, что должен был голосовать и принимать ... lol. – victorhooi

ответ

2

Поскольку кажется, что вы хотите, чтобы UserProfile или Department имели потенциально много адресов, ваши ForeignKeys отстают. Один экземпляр ForeignKey может указывать только на один экземпляр модели, тогда как нет ограничений на количество ForeignKeys, которые могут указывать на один экземпляр модели. Таким образом, ваш ForeignKey должен быть в адресе (в этом случае ваш inline будет работать как есть).

Ужасный фактор заключается в том, что у вас есть одна модель адреса, и вы хотите связать ее с двумя другими моделями; один ForeignKey on Address не может указывать как на UserProfile, так и на Department. Одним из решений является наличие двух адресных моделей (DepartmentAddress, с ForeignKey для отдела и UserAddress, с ForeignKey для UserProfile). Вы могли бы уменьшить дублирование в своем коде, получив оба наследуемых от abstract base class, содержащих все поля данных, но в вашей базе данных вы по-прежнему получаете две в основном идентичные таблицы.

Другой вариант - иметь GenericForeignKey адрес, который может указывать на экземпляр любой модели. Затем ваш inline должен стать GenericInlineModelAdmin. Это нарушает нормальную нормализацию базы данных и не позволяет вашей базе данных выполнять правильную проверку целостности. Если бы у вас было потенциально больше моделей в будущем, у которых также были бы адреса, я бы подумал об этом; если он, скорее всего, будет ограничен только двумя текущими, я могу пойти с вышеуказанным вариантом.

+0

А ... В моем редактировании я использовал подход один. – cethegeek

+0

heya, Coolies, спасибо за это. Итак, вы говорите, что поле FK должно быть в адресе, а не в UserProfile/Department. Должен попытаться обернуться вокруг этого - так, как это обычно делается в теории БД, если это были таблицы SQL? Как бы вы справились с этим конкретным случаем с общей таблицей адресов в теории SQL? Я думаю, что могу попробовать абстрактный подход базового класса, кажется меньше работы, чем GenericRelations ... lol. Все будет хорошо работать с интерфейсом администратора, верно, потому что эти два подкласса Address будут по существу разными объектами? Cheers, Victor – victorhooi

+0

Victor: да, в прямом SQL вы все равно поместите поле внешнего ключа на «одну» сторону отношений «много-к-одному». И да, абстрактное решение базового класса будет хорошо работать с встроенными лимитами администратора (по крайней мере, один). –

0

Я прочитал ваши модели что вы хотите от вашей модели, как:

A department has one to many addresses

A department has one and only one user (as head of department)

A user (through his profile) belongs to one to many departments

A user (through his profile) has one to many addresses

Если это ваше намерение, а это означает, что нет ни одного случая, когда пользователь не будет иметь адрес или отдел, и ни одного случая, когда ведомство не будет иметь адрес или руководитель отдела; то я бы сказал, ваши модели ОК следует читать:

class Department(models.Model): 
    name = models.CharField(max_lenght=20) 
    head_of_department = models.OneToOneField(User) 
    address = models.ForeignKey(Address) 

class UserProfile(models.Model): 
    user = models.ForeignKey(User, unique=True) 
    address = models.ForeignKey(Address) 
    department = models.OneToOneField(Department) 

class Address(models.Model): 
    street_address = models.CharField(max_length=20) 
    ... 

    class Meta: 
     abstract = True 

class UserAddress(Address): 
    user_profile = models.ForeignKey(UserProfile) 

class DepartmentAddress(Address): 
    department = models.ForeignKey(Department) 

Подробнее о abstract classes.

То, что ваши модели не рассматривают, - это возможности того, что два пользователя будут иметь один и тот же адрес, и/или два отдела будут иметь один и тот же адрес. Поскольку вы не указываете уникальное ограничение на адрес (что я вижу), я предполагаю, что с вами в порядке с адресом реального мира, который появляется не один раз в вашей таблице адресов.

Если с вами все в порядке; хорошо.

Сообщение об ошибке, которое вы получаете, указывает на факт: в адресе в отдел отсутствует внешний ключ. Вам нужно будет вернуть эти отношения для работы inline. Значение, при редактировании адреса вы можете редактировать любые отделы, связанные с ним; но не наоборот. С предлагаемыми выше моделями вы не должны видеть эту ошибку.

См. example from the docs. Обратите внимание, как Author has many Books и как много сторон отношений является тем, который может быть встроенным.

+0

Этот ответ будет иметь смысл, за исключением того, что он, по-видимому, игнорирует фактический код модели, размещенный ;-) В котором ForeignKeys to Address находятся в UserProfile и Department, что означает, что каждый из них может иметь только один адрес, но адрес может быть принадлежащих многим организациям. –

+0

Dang мои плохие навыки чтения скорости ... Карл - как обычно - это правильно. Я исправлю свой ответ. Заслуженный -1, спасибо. – cethegeek

+0

Быстрое редактирование, -1 retracted ;-) –

Смежные вопросы