2010-07-11 6 views
29

Я нахожу противоречивую информацию о том, следует ли использовать OneToOneField (User) или ForeignKey (User, unique = True) при создании модели UserProfile путем расширения модели пользователя Django.Django: При расширении User лучше использовать OneToOneField (User) или ForeignKey (User, unique = True)?

Что лучше использовать это ?:

class UserProfile(models.Model): 
    user = models.ForeignKey(User, unique=True) 

или это ?:

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 

Django Doc задающий OneToOneField, в то время как Django Book example использует ForeignKey.

James Bennett также имеет два сообщения в блоге, что обеспечивающие противоречивые примеры, а также:

В первом посте, Беннет обеспечивает некоторые причины, почему он перешел к использованию ForeignKey вместо OneToOneField, но я не совсем понимаю, особенно когда вижу другие сообщения, которые рекомендуют обратное.

Мне любопытно узнать ваше предпочтение и почему. Или это даже имеет значение?

+0

Я ничего не вижу в первой статье Беннетта относительно профилей пользователей. –

+0

@ Игнасио - Извините, я добавил ссылку на неправильную статью. Должно быть, это был его пост «Расширение модели пользователя». Я исправил ссылку. Спасибо за указание на это. –

+0

Для меня, http://stackoverflow.com/questions/5870537/whats-the-difference-between-django-onetoonefield-and-foreignkey понятнее понимать –

ответ

17

Единственная настоящая причина, данная в статье, заключается в том, что ее можно настроить так, чтобы страница администратора для User отображала оба поля в User и UserProfile. Это может быть реплицировано с помощью OneToOneField с небольшой консистентной смазкой, поэтому, если вы не склонны показывать его на странице администратора без какой-либо работы за счет некоторой ясности («Мы можем создать несколько профилей на пользователя! , подождите, он настроен уникально. ») Я бы использовал OneToOneField.

7

Помимо ссылки на админ-страницу, другой причиной для решения ForeignKey является то, что он позволяет использовать правильный менеджер баз данных по умолчанию при обращении к объектам с обратным отношением. Рассмотрим пример из этого subclasses manager snippet. Допустим, что определение Post класса из примера выглядит следующим образом:

class Post(ParentModel): 
    title = models.CharField(max_length=50) 
    onetoone = models.ForeignKey(SomeModel, unique=True) 

    children = ChildManager() 
    objects = models.Manager() 

Позвонив somemodel_instance.post_set.all()[0], вы получите нужные подклассы объектов Post класса, как показаны путем определения первого менеджера (по умолчанию) в качестве ChildManager. С другой стороны, с OneToOneField, вызывая somemodel_instance.post, вы получаете экземпляр класса Post. Вы всегда можете позвонить somemodel_instance.post.subclass_object и получить тот же результат, но менеджер по умолчанию может выполнять любые другие трюки, а решения FK скрывают их.

Если вы являетесь владельцем и можете изменить код пользовательского менеджера, вы можете использовать атрибут use_for_related_fields вместо использования FK вместо допустимого поля 1to1, но даже это может завершиться неудачно из-за некоторых известных мне неудобств автоматических менеджеров. Насколько я помню, в приведенном выше примере не удастся.

5

Другая причина, как правило, не использует OneToOneField связанные с обратными отношениями: при использовании обратной связи, определенной с помощью OneToOneField вы получаете экземпляр модели, вопреки Manager для ForeignKey обратной связи и, как следствие, всегда есть DB удара.Это дорого, если вы делаете некоторые общие вещи по обратным отношениям (через _meta.get_all_related_objects()) и не знаете и не заботитесь, будете ли вы использовать их все или нет.

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