Может ли django auth_user.username быть varchar (75)? Как это можно сделать?

Есть ли что-то не так с работой таблицы alter на auth_user, чтобы сделать username be varchar(75), чтобы она могла соответствовать электронной почте? Что это может сломать?

Если вы должны были изменить auth_user.username как varchar(75), где вам нужно было бы изменить django? Это просто вопрос изменения 30 - 75 в исходном коде?

username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))

Или есть ли другая проверка в этом поле, которая должна быть изменена или какие-либо другие последствия для этого?

См. обсуждение комментария с bartek ниже относительно причины для этого.

Изменить. Оглядываясь на это через много месяцев. Для тех, кто не знает посылки: в некоторых приложениях нет требования или желания использовать имя пользователя, они используют только электронную почту для регистрации и авторизации. К сожалению, в django auth.contrib требуется имя пользователя. Вы можете начать отправлять письма в поле имени пользователя, но поле составляет всего 30 char, а электронные письма могут быть длинными в реальном мире. Потенциально даже дольше, чем предлагаемый здесь 75 char, но 75 char вмещает самые разумные адреса электронной почты. Вопрос направлен на эту ситуацию, поскольку она встречается приложениями на основе электронной почты.

Ответ 1

Есть способ достичь этого, не касаясь базовой модели и без наследования, но это определенно взломать, и я буду использовать его с особой осторожностью.

Если вы посмотрите на файл Django doc на сигналах, вы увидите там один под названием class_prepared, который в основном отправляется после того, как любая фактическая модель класс был создан метаклассом. Этот момент - ваш последний шанс модифицировать любую модель до того, как произойдет какая-либо магия (например: ModelForm, ModelAdmin, syncdb и т.д.).

Итак, план прост, вы просто регистрируете этот сигнал с помощью обработчика, который будет обнаруживать, когда он вызывается для модели User, а затем измените свойство max_length поля username.

Теперь вопрос в том, где должен жить этот код? Он должен быть выполнен до загрузки модели User, поэтому часто это означает очень рано. К сожалению, вы не можете (django 1.1.1, не проверять с другой версией), поместите это в settings, потому что импорт signals там будет нарушен.

Лучшим выбором было бы разместить его в модуле моделей манекенов и поместить это приложение поверх списка INSTALLED_APPS/tuple (чтобы он импортировался раньше всего). Вот пример того, что вы можете иметь в myhackishfix_app/models.py:

from django.db.models.signals import class_prepared

def longer_username(sender, *args, **kwargs):
    # You can't just do `if sender == django.contrib.auth.models.User`
    # because you would have to import the model
    # You have to test using __name__ and __module__
    if sender.__name__ == "User" and sender.__module__ == "django.contrib.auth.models":
        sender._meta.get_field("username").max_length = 75

class_prepared.connect(longer_username)

Это сделает трюк.

Несколько заметок:

  • Возможно, вы захотите изменить также поле help_text для отображения новой максимальной длины
  • Если вы хотите использовать автоматический администратор, вам придется подклассы UserChangeForm, UserCreationForm и AuthenticationForm, поскольку максимальная длина не выводится из поля модели, а непосредственно в объявлении поля формы.

Если вы используете South, вы можете создать следующую миграцию, чтобы изменить столбец в базовой базе данных:

import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):

        # Changing field 'User.username'
        db.alter_column('auth_user', 'username', models.CharField(max_length=75))


    def backwards(self, orm):

        # Changing field 'User.username'
        db.alter_column('auth_user', 'username', models.CharField(max_length=35))


    models = { 

# ... Copy the remainder of the file from the previous migration, being sure 
# to change the value for auth.user / usename / maxlength

Ответ 2

Основанный на Clément и Matt Miller, отличный комбинированный ответ выше, я собрал быстрое приложение, которое его реализует. Пип-установка, миграция и переход. Поставил бы это как комментарий, но еще не имеет его!

https://github.com/GoodCloud/django-longer-username

EDIT 2014-12-08

Вышеупомянутый модуль теперь устарел в пользу https://github.com/madssj/django-longer-username-and-email

Ответ 3

Обновленное решение для версии Django 1.3 (без изменения manage.py):

Создайте новое django-приложение:

monkey_patch/
    __init__.py
    models.py

Установите его как сначала: (settings.py)

INSTALLED_APPS = (
    'monkey_patch', 
    #...
)

Вот модели .py:

from django.contrib.auth.models import User
from django.core.validators import MaxLengthValidator

NEW_USERNAME_LENGTH = 300

def monkey_patch_username():
    username = User._meta.get_field("username")
    username.max_length = NEW_USERNAME_LENGTH
    for v in username.validators:
        if isinstance(v, MaxLengthValidator):
            v.limit_value = NEW_USERNAME_LENGTH

monkey_patch_username()

Ответ 4

Вышеупомянутые решения, похоже, обновляют длину модели. Однако, чтобы отразить вашу пользовательскую длину в admin, вам также необходимо переопределить формы администратора (к сожалению, они не просто наследуют длину от модели).

from django.contrib.auth.forms import UserChangeForm, UserCreationForm

UserChangeForm.base_fields['username'].max_length = NEW_USERNAME_LENGTH
UserChangeForm.base_fields['username'].widget.attrs['maxlength'] = NEW_USERNAME_LENGTH
UserChangeForm.base_fields['username'].validators[0].limit_value = NEW_USERNAME_LENGTH
UserChangeForm.base_fields['username'].help_text = UserChangeForm.base_fields['username'].help_text.replace('30', str(NEW_USERNAME_LENGTH))

UserCreationForm.base_fields['username'].max_length = NEW_USERNAME_LENGTH
UserCreationForm.base_fields['username'].widget.attrs['maxlength'] = NEW_USERNAME_LENGTH
UserCreationForm.base_fields['username'].validators[0].limit_value = NEW_USERNAME_LENGTH
UserCreationForm.base_fields['username'].help_text = UserChangeForm.base_fields['username'].help_text.replace('30', str(NEW_USERNAME_LENGTH))

Ответ 6

Если вы просто измените таблицу базы данных, вам все равно придется иметь дело с проверкой Django, поэтому она не позволит вам сделать более 30 символов. Кроме того, имя пользователя проверяется так, что у него не могут быть специальные символы, такие как @, поэтому простое изменение длины поля не будет работать. Неплохо, похоже, что он справляется с этим. Здесь поле username из models.py в django.contrib.auth:

username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))

Создание авторизации электронной почты не сложно. Здесь вы можете использовать супер простой почтовый сервер электронной почты. Вы должны сделать это после добавления дополнительной проверки, чтобы убедиться, что адрес электронной почты уникален, и все готово. Это легко.

Ответ 7

Да, это можно сделать. По крайней мере, я думаю, что это должно сработать; Я закончил замену всей модели auth, поэтому я готов исправляться, если это не сработает...

Если у вас нет записей о пользователях, о которых вы заботитесь:

  • удалить таблицу auth_user
  • измените имя пользователя на max_length = 75 в модели
  • SyncDB

Если у вас есть учетные записи пользователей, вам нужно сохранить их более сложными, поскольку вам нужно каким-то образом их перенести. Самый простой - это резервное копирование и восстановление данных из старой в новую таблицу, что-то вроде:

  • резервное копирование данных таблицы пользователя
  • удалить таблицу
  • SyncDB
  • reimport пользовательские данные в новую таблицу; чтобы восстановить исходные значения id

В качестве альтернативы, используя свой безумный навык python-django, скопируйте экземпляры модели пользователя из старого в новый и замените:

  • создайте свою собственную модель и временно оставите ее рядом с моделью по умолчанию.
  • напишите script, который копирует экземпляры из модели по умолчанию в новую модель
  • замените модель по умолчанию на свой собственный

Последнее не так сложно, как кажется, но, очевидно, требует немного больше работы.

Ответ 8

В основном проблема заключается в том, что некоторые люди хотят использовать адрес электронной почты в качестве уникального идентификатора, тогда как система аутентификации пользователя в Django требует уникального имени пользователя не более 30 символов. Возможно, это изменится в будущем, но это случай с Django 1.3, который я пишу.

Мы знаем, что 30 символов слишком короткие для многих адресов электронной почты; даже 75 символов недостаточно для представления некоторых адресов электронной почты, как описано в Какова оптимальная длина для адреса электронной почты в базе данных?.

Мне нравятся простые решения, поэтому я рекомендую хэшировать адрес электронной почты в имя пользователя, которое соответствует ограничениям для имен пользователей в Django. Согласно Идентификация пользователя в Django, имя пользователя должно быть не более 30 символов, состоящее из буквенно-цифровых символов и _, @, +,. а также -. Таким образом, если мы используем кодировку base-64 с тщательной подстановкой специальных символов, у нас есть до 180 бит. Таким образом, мы можем использовать 160-битную хеш-функцию, такую ​​как SHA-1, следующим образом:

import hashlib
import base64

def hash_user(email_address):
    """Create a username from an email address"""
    hash = hashlib.sha1(email_address).digest()
    return base64.b64encode(hash, '_.').replace('=', '')

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

Ответ 9

Просто добавьте нижеприведенный код в нижней части settings.py

from django.contrib.auth.models import User
User._meta.get_field("username").max_length = 75

Ответ 10

Я использую django 1.4.3, что делает его довольно простым, и мне не пришлось ничего менять в моем коде после того, как я понял, что хотел использовать длинные адреса электронной почты в качестве имен пользователей.

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

В вашей модели приложения (myapp/models.py) добавьте следующее

from django.contrib.auth.models import User

class UserProfile(models.Model):

    # This field is required.
    User._meta.get_field("username").max_length = 100
    user = models.OneToOneField(User)

Затем в вашем файле settings.py указывается модель:

AUTH_USER_MODEL = 'myapp.UserProfile'

Ответ 11

Лучшее решение - использовать поле электронной почты для электронной почты и имя пользователя для имени пользователя.

В подтверждении формы входа в систему, найдите, являются ли данные именем пользователя или электронной почтой, а также электронной почтой, запросите поле электронной почты.

Это требует, чтобы обезьяна исправляла contrib.auth.forms.login_form, которая представляет собой несколько строк в соответствующем представлении.

И это намного лучше, чем пытаться изменить модели и таблицы базы данных.

Ответ 12

Если вы используете venv (виртуальная среда), самым простым решением, вероятно, является просто обновление основного кода напрямую, то есть открытие следующих двух файлов: - - venv/lib/python2.7/sites-packages/django/contrib/auth/model.py - venv/lib/python2.7/sites-packages/django/contrib/auth/forms.py Найдите все имя пользователя и измените max_length от 30 до 100. Это безопасно, поскольку вы уже используете venv, поэтому он не повлияет на какой-либо другой проект Django.