Подтвердить что ты не робот

Избавиться от get_profile() при переходе на Django 1.6

С Django 1.5 и внедрением пользовательских моделей модель AUTH_PROFILE_MODULE стала устаревшей. В моем существующем приложении Django я использую модель User, и у меня также есть модель Profile с внешним ключом для User и сохранение других сведений о пользователе в профиле. В настоящее время используется AUTH_PROFILE_MODULE, и для него установлено значение "app.profile".
Очевидно, что мой код имеет тенденцию делать много user.get_profile(), и теперь это должно исчезнуть.

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

Есть ли какой-либо способ - и без миграции модели - и только путем создания/переопределения функции get_profile() с чем-то вроде my_user.userprofile_set.all()[0]) где-нибудь?

Кто-нибудь, кто пошел по этому пути и может делиться идеями или опытом?

Если я снова сделаю эту услугу - очевидно, не будет идти так, но с полу-большой живой системой производства я открыт для коротких сокращений: -)

4b9b3361

Ответ 1

Использование модели профиля с отношением к встроенному User по-прежнему является полностью законной конструкцией для хранения дополнительной информации пользователя (и рекомендуется во многих случаях). Материалы AUTH_PROFILE_MODULE и get_profile(), которые теперь устарели, просто оказались ненужными, учитывая, что встроенный синтаксис Django 1-к-1 работает здесь чисто и элегантно.

Переход от старого использования на самом деле прост, если вы уже используете OneToOneField до User в своей модели профиля, что означает модуль профиля был рекомендован для настройки до того, как get_profile устарел.

class UserProfile(models.Model):
    user = OneToOneField(User, related_name="profile")
    # add profile fields here, e.g.,
    nickname = CharField(...)

# usage: no get_profile() needed. Just standard 1-to-1 reverse syntax!
nickname = request.user.profile.nickname  

Смотрите здесь, если вы не знакомы с синтаксической магией для OneToOneField, что делает это возможным. В результате он становится простым поиском и заменой get_profile() для profile или любым вашим related_name (автосоединенное имя в приведенном выше случае будет user_profile). Стандартный синтаксис django reverse 1-1 на самом деле лучше, чем get_profile()!

Измените ForeignKey на OneToOneField

Однако я понимаю, что это не полностью отвечает на ваш вопрос. Вы указываете, что вы использовали ForeignKey to User в своем модуле профиля, а не в OneToOne, что хорошо, но синтаксис не так прост, если оставить его как ForeignKey, как вы заметили в ваш комментарий. Предполагая, что вы использовали ваш ForeignKey на практике как уникальный внешний ключ (по существу, от 1 до 1), учитывая, что в БД a OneToOneField - это всего лишь ForeignKey поле с ограничением unique=True, вы должны иметь возможность изменить поле ForeignKey на OneToOneField в своем коде, не выполняя при этом значительную миграцию базы данных или не используя потери данных.

Работа с миграцией юга

Если вы используете South для переноса, изменение кода из предыдущего раздела может смутить Юг для удаления старого поля и создавая новый, если вы выполните schemamigration --auto, поэтому вам может потребоваться вручную изменить миграцию, чтобы все было правильно. Один из подходов состоял бы в том, чтобы создать схематизацию, а затем затушить методы вперед и назад, чтобы на самом деле ничего не пытаться сделать, но так, что она по-прежнему автоматически замораживает модель как OneToOneField. Затем, если вы хотите делать все отлично, вы должны добавить уникальное ограничение в соответствующий столбец внешнего ключа базы данных. Вы можете сделать это вручную с помощью SQL или через Юг (либо вручную отредактировав методы миграции, либо установив unique=True в ForeignKey и создав первую миграцию South, прежде чем переключать ее на OneToOneField и выполнять вторая миграция и затухание методов вперед/назад).