Puede django del auth_user.nombre de usuario se varchar(75)? Cómo podría hacerse?

Hay nada malo con la ejecución de alter table en auth_user para hacer username ser varchar(75) lo que puede caber un correo electrónico? Lo que hace que se rompen si nada?

Si desea cambiar auth_user.username a ser varchar(75) donde se tendría que modificar django? Es simplemente una cuestión de cambiar de 30 a 75 en el código fuente?

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

O hay otros validación en este campo que habría que cambiar o cualquier otro repercusiones para hacerlo?

Véase el comentario de la discusión con bartek a continuación con respecto a la razón para hacerlo.

Editar: Mirando hacia atrás en esto después de muchos meses. Para quien no conoce la premisa: Algunas aplicaciones no tienen un requisito o deseo de utilizar un nombre de usuario, sólo utilizan el correo electrónico para el registro & auth. Por desgracia, en django auth.contrib, nombre de usuario es obligatorio. Usted podría empezar a poner mensajes de correo electrónico en el campo nombre de usuario, pero el campo es de sólo 30 char y correos electrónicos puede ser larga en el mundo real. Potencialmente, incluso más que el 75 char que aquí se sugiere, pero 75 char adapta a la mayoría de cuerda direcciones de correo electrónico. La pregunta es dirigida a esta situación, tal como se encuentra por correo electrónico-auth-aplicaciones basadas en.

  • Antes de la edición no era una pregunta por una larga queja sobre auth.contrib. Editado para que sea más civil, pero afirma que el «voto es demasiado viejo para cambiar».
  • He editado para ser más conciso, yo no resentirse de su lo que implica menos de los civiles (?). Me estaba explicando la lógica de preguntar acerca de auth_user.nombre de usuario = varchar(75). Es una situación que veo un montón de otras personas en lo que es la pena explicar. Pero no se si es causa de que las personas no se toman el tiempo para abordar la cuestión.
  • Nota para la posteridad: Django 1.5 tiene algunas características que resolver estos problemas de manera más elegante. Consulte procrastinatingdev.com/django/…
InformationsquelleAutor Purrell | 2010-04-09

13 Kommentare

  1. 78

    Hay una manera de lograr que, sin tocar el núcleo del modelo, y sin herencia, pero definitivamente hackish y me gustaría usarlo con cuidado extra.

    Si usted mira Django doc en las señales, verás que hay uno llamado class_prepared, que básicamente es enviado una vez que el modelo actual de la clase ha sido creado por el metaclass. Ese momento es su última oportunidad de la modificación de cualquiera de los modelos antes de cualquier magia se lleva a cabo (es decir: ModelForm, ModelAdmin, syncdb, etc…).

    Así que el plan es simple, usted sólo tiene que registrar que la señal con un controlador que se va a detectar cuando es llamado por el User modelo y, a continuación, cambiar el max_length propiedad de la username campo.

    Ahora la pregunta es, ¿dónde debe este código vidas? Tiene que ser ejecutado antes de la User modelo se carga, por lo que a menudo significa muy temprano. Desafortunadamente, usted no puede (django 1.1.1, no comprobar con otra versión) puesto que en settings debido a la importación de signals no va a romper cosas.

    Una mejor opción sería ponerlo en un maniquí de la aplicación de los modelos de módulo, y hacer que la aplicación en la parte superior de la INSTALLED_APPS la lista o tupla (por lo que se obtiene importados antes de cualquier otra cosa). Aquí es un ejemplo de lo que se puede tener en 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)

    Que va a hacer el truco.

    Un par de notas: la

    • Es posible que desee cambiar también el help_text del campo, para reflejar la nueva longitud máxima
    • Si desea utilizar el sistema automático de administración, tendrá subclase UserChangeForm, UserCreationForm y AuthenticationForm como la longitud máxima no se deduce a partir del modelo de campo, sino directamente en el formulario de declaración de campo.

    Si usted está usando Sur, puede crear los siguientes migración para cambiar la columna en la base de datos subyacente:

    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
    • Solución interesante, trato de mayo de este. Una nota a cualquier persona que viene a través de este post que quiera probar esta y es también el uso de mysql: Con esta solución, ya que el campo es todavía de tipo varchar(30) en db (a menos que lo ejecute alter table para modificar el nombre de usuario varchar(75)), esto sólo funcionará si mysql se ejecuta en ‘estricto’ modo: dev.mysql.com/doc/refman/5.0/en/char.html, de lo contrario los valores de más de 30 será truncado en la base de datos
    • sí, usted tiene que alter table a sí mismo como django no lo va a hacer por usted (usted puede ser que desee probar, sur para que). Pero un syncdb a partir de la nada crear el campo con el tipo correcto (varchar(75)).
    • He sugiere modificaciones a la respuesta de incluir la migración para el Sur, ya que tomó un poco de investigación para mi trabajo y es demasiado largo para un comentario.
    • FYI, el SQL apenas para la referencia (más corto que escribir el Sur de la migración): ALTER TABLE auth_user ALTERAR la COLUMNA nombre de usuario de TIPO varchar(75);
    • para django1.3 necesitaba para poner esto en manage.py después de llamar a setup_environ, antes de execute_manager. Yo también necesitaba añadir sender._meta.get_field('username').validators[0].limit_value = 75 ¿alguien tiene alguna forma mejor para lograr esto en django1.3?
    • Yo no era consciente de la class_prepared de la señal. Interesante enfoque. +1
    • Quiso decir «max_length=30» en lugar de «max_length=35» en el Sur de atrás de la migración?
    • Se puede hacer esto con 1,7 migraciones? No estoy seguro de cómo especificar la aplicación de la etiqueta como ‘auth’.
    • No, no trabajo en Django 1.7. La buena noticia es que el núcleo del equipo está buscando en él: code.djangoproject.com/ticket/20846 // groups.google.com/forum/#!tema/django-desarrolladores/v3wYKWWYFT4/…
    • No creo que se implementó en Django 1.9.2.

  2. 25

    Basado en Clément y Matt Miller gran combinación respuesta de arriba, he reunido una aplicación rápida que la implementa. Pip instalación, migración, y se van. Iba a poner esto como un comentario, pero no tienen el cred todavía!

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

    EDITAR 2014-12-08

    El anterior módulo está ahora en desuso en favor de https://github.com/madssj/django-longer-username-and-email

    • Gracias @skoczen ! Funciona muy bien para mí hasta ahora
    • He intentado esto, pero estoy recibiendo de error «no Hay ningún Sur de la base de datos del módulo de ‘sur.db.mysql’ para la base de datos. Por favor, seleccione una base de datos compatible, compruebe SOUTH_DATABASE_ADAPTER[S] configuración, o quitar el Sur de INSTALLED_APPS.»
  3. 21

    Solución actualizada para el Django de la versión 1.3 (sin modificar manage.py):

    Crear nuevos django-app:

    monkey_patch/
        __init__.py
        models.py

    Instalarlo como el primero: (settings.py)

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

    Aquí es 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()
    • Me trató de esa solución porque parece mucho más sencillo, pero tengo el mismo resultado «valor demasiado largo para el tipo character varying(30)». Hice todo lo que es exactamente como usted indicó. Estoy en django 1.3.3
  4. 5

    Las soluciones anteriores no parecen actualizar el modelo de longitud. Sin embargo, para reflejar su longitud personalizada en admin, usted también necesita reemplazar el administrador de formularios (y frustrante, no sólo tiene que heredar de la longitud de la modelo).

    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))
    • también puede ser que desee aplicar la misma lógica a AuthenicationForm en django.contrib.auth.formas
    • esto no parece funcionar con AUTH_USER_MODEL
  5. 1

    Si simplemente modificar la tabla de base de datos, usted todavía tiene que lidiar con Django de validación, por lo que no puede hacer uno de los más de 30 personajes de todos modos. Además, el nombre de usuario valida por lo que no puede tener caracteres especiales como @ así que simplemente modificando la longitud del campo no trabajar de todos modos. Mi mal, se ve como se maneja eso. Aquí está el campo nombre de usuario de models.py en django.contrib.auth:

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

    La creación de correo electrónico auth no es difícil. He aquí un super simple de correo electrónico auth backend puede utilizar. Al l lo que usted necesita hacer después de que se agregue algunas de validación para asegurar que la dirección de correo electrónico es único y está hecho. Que fácil.

    • No del todo. Qué se puede hacer con el campo nombre de usuario? Todavía es una clave principal.
    • También estás equivocado sobre el signo @ en los nombres de usuario. Permite la @. De hecho, no acabo de ver donde se impone la < 30 en el nombre de usuario de mirar el código. No estoy diciendo que no hay, pero son usted seguro de que está ahí?
    • No es una clave principal. El nombre de usuario es fácil. Tienes su correo electrónico y una clave principal de la base de datos, tal vez su apellido también. Oh, usted también tiene un generador de números aleatorios construido en python .. y así sucesivamente. Acaba de hacer el nombre de usuario algo único. En una de mis aplicaciones acabo de utilizar la primera parte del correo electrónico, además de su id de usuario. Simple para aplicaciones básicas.
    • Sí que, realmente, no es una solución suficiente si usted piensa acerca de ello. ¿Cómo se garantiza el nombre de usuario es único. Tenga en cuenta que, en realidad, usted no puede usar el id en el nombre de usuario, porque al crear el objeto de usuario en realidad no tiene un id, y el nombre de usuario es obligatorio. Tal vez que no era una aplicación de django. Así que quedamos con el hash si realmente quieres hacer es robusto. Pero lo que me pregunto es ¿por qué ir a través de todo este problema si sólo se puede modificar django para aceptar direcciones de correo electrónico en los nombres de usuario?
    • Funciona muy bien para mí. Hay maneras fáciles para comprobar si algo es único (comparar su valor a la base de datos, repita si es necesario.) Se que la gestión de una empresa de la aplicación? A continuación, puede que tenga que buscar otras soluciones. Si usted está ejecutando una aplicación con unos pocos miles de usuarios, creo que no tendrás ningún problema. El problema con la modificación del código de django y la tabla en sí está bien .. imaginar cuando tenga que actualizar django. Que ahora roto, y tiene una pesadilla de mantenimiento en el largo plazo
    • Sí, la empresa de la aplicación. Poner un hash en el nombre de usuario y el manejo de excepciones para reintentar la colisión es la mejor cosa a hacer para esta sin la modificación de django parece (?). Estoy usando base64(md5) (por lo que cabe). Realmente estoy preguntando si esto es menos de una molestia de la modificación de los pocos lugares en django donde tienes el nombre de usuario longitud definida y utilizada. Obviamente, usted tiene que mantener que si/cuando la actualización de django. Pero yo no lo llamaría necesariamente que una pesadilla.
    • Si usted encuentra un hash método que va a funcionar y ser único, entonces genial. No creo que la adición de una costumbre de backend y, a continuación, algunos de validación adicional dentro de sus formas, es que la cantidad de trabajo con respecto a la modificación de Django código fuente.
    • Depende de la cantidad de trabajo que realmente es. Todo lo que puedo ver es la definición del modelo que has publicado anteriormente. No parece muy difícil, pero que no ve ningún otro tipo de validación. Si es tan fácil como cambiar la línea a max_length(75) (django le gusta el 75 char mensajes de correo electrónico) así que es bastante fácil. Y usted no tiene que mantener su propia autenticación de backend o de residuos de todo este espacio en la base de datos y calcular los ciclos de fulfulling la única restricción de nombre de usuario.

  6. 1

    Sí, se puede hacer. Al menos creo que debería de trabajo; terminé la sustitución de todo el auth modelo, por lo que estoy dispuesto a ser corregido si esto no funciona…

    Si usted no tiene los registros de usuario que te importa:

    1. caída de la auth_user tabla
    2. cambiar el nombre de usuario para max_length=75 en el modelo
    3. syncdb

    Si usted tiene los registros de usuario que usted necesita conservar, entonces es más complicado ya que es necesario migrar ellos de alguna manera. Más fácil de copia de seguridad y restauración de los datos de la vieja a la nueva tabla, algo así como:

    1. de copia de seguridad al usuario los datos de la tabla
    2. caída de la tabla
    3. syncdb
    4. volver a importar los datos del usuario a la nueva tabla; teniendo cuidado de restaurar el valor original de los valores de id

    Alternativamente, el uso de su mad python-django skillz, copie el modelo de usuario instancias de la vieja a la nueva y reemplazar:

    1. crear el modelo personalizado y temporalmente de pie junto a la modelo por defecto
    2. escribir un script que copia las instancias desde el modelo predeterminado para el nuevo modelo de
    3. reemplazar el modelo predeterminado con su encargo uno

    El último no es tan difícil como parece, pero, obviamente, implica un poco más de trabajo.

  7. 1

    Fundamentalmente, el problema es que algunas personas quieren utilizar una dirección de correo electrónico como identificador único, mientras que el usuario del sistema de autenticación de Django requiere un nombre de usuario único de más de 30 caracteres. Tal vez eso va a cambiar en el futuro, pero ese es el caso con Django 1.3 como estoy escribiendo.

    Sabemos que el 30 caracteres es demasiado corta para tantas direcciones de correo electrónico; hasta 75 caracteres no es suficiente para representar algunas direcciones de correo electrónico, como se explica en ¿Cuál es la longitud óptima para una dirección de correo electrónico en una base de datos?.

    Me gusta soluciones simples, por lo que recomendamos el hash de la dirección de correo electrónico en un nombre de usuario que se adapta a las restricciones para los nombres de usuario en Django. De acuerdo a La autenticación de usuario en Django, un nombre de usuario debe estar a más de 30 personajes, que consta de caracteres alfanuméricos y _, @, +, . y -. Así, si utilizamos de base 64 de la codificación con el cuidado de la sustitución de los caracteres especiales, tenemos hasta 180 bits. Por lo que podemos utilizar un hash de 160 bits función como SHA-1 de la siguiente manera:

    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('=', '')

    En resumen, esta función se asocia a un usuario para cualquier dirección de correo electrónico. Soy consciente de que hay una pequeña probabilidad de una colisión en la función de hash, pero esto no debería ser un problema en la mayoría de las aplicaciones.

    • ¿Por qué perder los ciclos de calcular el hash y el espacio de disco para almacenar? También tenga en cuenta que usted necesita para escribir, ya sea una costumbre de autorización de backend o de una costumbre login_form para hacer este trabajo. No es un gran negocio, pero todo parece como una extraña contorsión para mí.
    • En mi caso, hash ciclos y espacio en disco son mucho más baratos que el tiempo de desarrollo. Su kilometraje puede variar.
  8. 0

    Acaba de añadir el siguiente código en la parte inferior de settings.py

    from django.contrib.auth.models import User
    User._meta.get_field("username").max_length = 75
    • No trabajo en Django 1.7 y, más tarde, los modelos no han sido importado aún
  9. 0

    C:…\venv\Lib\site-packages\django\contrib\auth\models.py

    nombre = modelos.CharField(_(‘nombre’), max_length=30, blank=True)

    cambio

    nombre = modelos.CharField(_(‘nombre’), max_length=75, blank=True)

    guardar

    y el cambio en la base de datos

  10. -1

    Estoy usando django 1.4.3 cual hace que sea bastante fácil y no tuve que cambiar nada en mi código después de darse cuenta de que yo quería para el uso a largo direcciones de correo electrónico como nombres de usuario.

    Si usted tiene acceso directo a la base de datos, cambiar allí a la cantidad de personajes con los que te gustaría, en mi caso 100 caracteres.

    En su aplicación (modelo de myapp/models.py) agregar el siguiente

    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)

    A continuación, en su settings.py especifique el modelo:

    AUTH_USER_MODEL = 'myapp.UserProfile'
  11. -2

    La mejor solución es utilizar el campo de correo electrónico para el correo electrónico y el nombre de usuario nombre de usuario.

    En la entrada de formulario de inicio de sesión de validación, averiguar si los datos de nombre de usuario o el correo electrónico y si de correo electrónico, consulta el campo de correo electrónico.

    Esto sólo requiere monkey patching la contrib.auth.forms.login_form que es un par de líneas en la vista correspondiente.

    Y es mucho mejor que tratar de modificar los modelos y de las tablas de base de datos.

    • Creo que lo han entendido bien el problema, se trata de cuando no la estés utilizando nombres de usuario, usted está utilizando mensajes de correo electrónico. Y para resolver sin tocar django, generalmente aceptado, la solución es más de lo que se describe aquí. Es en realidad para rellenar el nombre de usuario con algo único (perdiendo el campo) y la creación de un AUTHORIZATION_BACKENDS clase para manejar la autenticación de correo electrónico. El problema es con la creación de los usuarios. Hay un campo de correo electrónico, pero también hay una necesaria campo nombre de usuario que no se ajustan a un correo electrónico. Siguen siendo necesarias para crear un nombre de usuario único cada vez que se crea un usuario.
    • perrierism: La solución a utilizar el correo electrónico solo, sin tocar django, es, obviamente, utilizando una muestra aleatoria de auto-generada nombre de usuario y el uso de correos electrónicos para la consulta (con el correo electrónico auth backend).
    • No era, obviamente,’ antes porque eso es en realidad una solución diferente de lo que has publicado. La solución que usted está mencionando ahora no requieren cambio de contrib.auth.los formularios.login_form. También la cuestión de la auto-generado los nombres de usuario no es tan sencillo si desea una robusta implementación, (ver la discusión con bartek). Por último, tenga en cuenta que la pregunta no es, «¿cómo hacer esto sin la modificación de django?». La aceptación general de la solución para que (el que no he hecho indicado) es conocida pero tiene sus limitaciones. Es decir, que usted todavía necesita único de los nombres de usuarios en la creación del usuario.
  12. -2

    Si usted está usando venv (entorno virtual), la solución más sencilla es probablemente acabo de actualizar el núcleo de código directamente, es decir, la apertura de los dos archivos siguientes:
    – – venv/lib/python2.7/sites-packages/django/contrib/auth/model.py
    – venv/lib/python2.7/sites-packages/django/contrib/auth/forms.py
    Buscar todo el campo nombre de usuario y cambiar max_length de 30 a 100. Es seguro, ya que ya están utilizando venv para que no afecte a cualquier otro proyecto de Django.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea