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

Что-то не так с запуском alter table на auth_user делать username быть 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 символов, и в реальном времени электронные письма могут быть длинными. Потенциально даже дольше, чем 75 символов, предложенных здесь, но 75 символов соответствуют большинству вменяемых адресов электронной почты. Вопрос нацелен на эту ситуацию, с которой сталкиваются приложения, основанные на аутентификации электронной почты.

13 ответов

Решение

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

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

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

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

Лучше было бы поместить его в модуль моделей фиктивного приложения и поместить это приложение поверх INSTALLED_APPS list / 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 максимальная длина выводится не из поля модели, а непосредственно в объявлении поля формы.

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

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

Основываясь на великолепном комбинированном ответе Клемента и Мэтта Миллера, я собрал быстрое приложение, которое его реализует. Pip установить, мигрировать и идти. Поставил бы это как комментарий, но еще не получил кредит!

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

РЕДАКТИРОВАТЬ 2014-12-08

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

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

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

monkey_patch/
    __init__.py
    models.py

Установите его как первый: (settings.py)

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

Вот models.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()

Представленные выше решения, похоже, обновляют длину модели. Однако, чтобы отразить вашу пользовательскую длину в 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))

Насколько я знаю, с Django 1.5 можно переопределить пользовательскую модель, которая решит проблему. Простой пример здесь

Если вы просто измените таблицу базы данных, вам все равно придется иметь дело с проверкой Django, так что в любом случае она не позволит вам создать более 30 символов. Кроме того, имя пользователя проверяется таким образом, что оно не может содержать специальные символы, такие как @ так что простое изменение длины поля не сработало бы в любом случае. Мой плохой, похоже, он справляется с этим. Вот поле имени пользователя из 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"))

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

По сути, проблема в том, что некоторые люди хотят использовать адрес электронной почты в качестве уникального идентификатора, в то время как система аутентификации пользователей в 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('=', '')

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

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

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

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

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

  1. резервное копирование данных таблицы пользователя
  2. бросить стол
  3. SyncDB
  4. повторно импортировать данные пользователя в новую таблицу; заботиться о восстановлении первоначальных значений идентификаторов

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

  1. создайте свою модель и временно поместите ее рядом с моделью по умолчанию
  2. написать скрипт, который копирует экземпляры из модели по умолчанию в новую модель
  3. замените модель по умолчанию своей

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

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

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

C:...\venv\Lib\ сайт-пакеты \ Джанго \ вно \ Auth \ models.py

first_name = models.CharField(_('имя'), max_length=30, пробел =True)

изменить на

first_name = models.CharField(_('имя'), max_length=75, пробел =True)

спасти

и изменить в базе данных

Я использую 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'

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

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

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

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

Если вы используете 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.

Другие вопросы по тегам