2009-09-09 3 views
4

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

Я попытался добавить поле с помощью (после того, как определены все мои модели и т.д. без ошибок, в соответствии с python manage.py validate):

User.add_to_class('location', models.CharField(max_length=250,blank=True))

и выполнил команду syncdb. Тем не менее, я продолжаю получать эту ошибку

OperationalError: no such column: auth_user.location

Является ли я в административном режиме сайта или оболочки manage.py. Должен быть дополнительный шаг, который мне не хватает, но, похоже, существует ограниченная документация по всей технике патчей обезьян. Поэтому я прошу вас о помощи, прежде чем прибегать к наследованию. Любой код, советы или указатели на дополнительную документацию, конечно, приветствуются.

Заранее спасибо.

PS. Я знаю, что эта техника уродливая и, вероятно, не рекомендуется. ;)

ответ

7

Когда вы добавляете поле в любую модель, даже если вы делаете это «официальным» способом, вам нужно перенести базу данных - Django не делает это за вас. Снимите стол и снова запустите ./manage.py syncdb.

Возможно, вам понадобится изучить одну из инфраструктур миграции, такую ​​как south, которая будет управлять подобными вещами для вас.

+0

Этот трюк! Хотя команда sqlall не показывала SQL, связанного с классом User. Благодаря! –

0

Структура Djangos использует метаклассы для инициализации таблиц. Это означает, что вы не можете обезьян-патч в новых столбцах, если вы не повторно инициализируете класс, который я не уверен, даже возможен. (Может быть).

Для получения дополнительной информации см. Difference between returning modified class and using type().

+0

Django делает всевозможные метаклассические обманки с полями при создании класса модели, но вызов метода add_to_class (как и у OP) - это точно правильный способ добавления нового поля динамически после этого (он выполняет необходимую обманку).Просто monkeypatching поле в качестве атрибута класса (без вызова add_to_class) не будет работать. Проблема здесь не имеет ничего общего с метаклассами, и все, что связано с отсутствием Django встроенной миграции схемы базы данных. –

+0

Ах. Меня обманули его ссылки на панировку обезьян, когда он на самом деле ничего не делает. –

0

Возможно, у вас могут возникнуть проблемы, связанные с определением вашего определения monkeypatch. Думаю, django syncdb создает таблицы данных только из «чистого» приложения auth, поэтому ваша модель будет без «местоположения», а затем ваш сайт с патчем будет искать поле.

Возможно, менее болезненный способ добавления дополнительной информации в профили пользователей описан in Django docs.

13

Существует альтернатива обеим подходам, которая заключается в простом использовании a related profile model. Это также хорошо документированный, очень рекомендуемый подход. Возможно, причина, по которой метод add_to_class не является документированным, как вы заметили, состоит в том, что это explicitly discouraged (по уважительной причине).

+0

Связанные профили, кажется, популярный способ обойти это. Стиль кодирования для ссылок на поля User, хотя и является довольно уродливым и несколько противоречивым для меня. Я обязательно изучу это. –

+0

+1: Просто используйте профиль, он отлично работает. –

+0

Это рекомендуемый способ расширения пользовательской системы в системе django.contrib.auth. Если вам нужно поддерживать эту систему в долгосрочной перспективе, использование профилей даст вам наилучшие шансы на чистую модернизацию самой инфраструктуры. – wlashell