update type example decimalfield django django-models

example - type models django



Cómo hacer que el campo de correo electrónico sea único en el modelo Usuario de contrib.auth en Django (18)

Precaución: El siguiente código fue escrito para una versión anterior de Django (antes de que se introdujeran los Modelos de Usuario Personalizado ). Contiene una condición de carrera, y solo debe usarse con un nivel de aislamiento de transacción de SERIALIZABLE y transacciones con alcance de solicitud.

Su código no funcionará, ya que los atributos de las instancias de campo son de solo lectura. Me temo que podría ser un poquito más complicado de lo que estás pensando.

Si solo crea instancias de usuario con un formulario, puede definir un ModelForm personalizado que aplique este comportamiento:

from django import forms from django.contrib.auth.models import User class UserForm(forms.ModelForm): class Meta: model = User def clean_email(self): email = self.cleaned_data.get(''email'') username = self.cleaned_data.get(''username'') if email and User.objects.filter(email=email).exclude(username=username).exists(): raise forms.ValidationError(u''Email addresses must be unique.'') return email

Luego solo use este formulario donde sea que necesite crear un nuevo usuario.

Por cierto, puede usar Model._meta.get_field(''field_name'') para obtener campos por nombre, en lugar de por posición. Así por ejemplo:

# The following lines are equivalent User._meta.fields[4] User._meta.get_field(''email'')

ACTUALIZAR

La documentación de Django recomienda utilizar el método de clean para todas las validaciones que abarcan múltiples campos de formulario, ya que se llama después de todos los métodos <FIELD>.clean y <FIELD>_clean . Esto significa que puede (en su mayoría) confiar en que el valor del campo está presente en cleaned_data desde dentro de clean .

Dado que los campos de formulario se validan en el orden en que se declaran, creo que está bien colocar ocasionalmente la validación de campo múltiple en un método <FIELD>_clean , siempre que el campo en cuestión aparezca después de todos los otros campos de los que depende. Hago esto para que los errores de validación estén asociados con el campo en sí, en lugar de con el formulario.

Necesito parchar el modelo de Usuario estándar de contrib.auth asegurándome de que la entrada del campo de correo electrónico sea única:

User._meta.fields[4].unique = True

¿Dónde está el mejor lugar en el código para hacer eso?

Quiero evitar el uso de los campos numéricos [4] . Es mejor para los campos de usuario [''email''] , pero fields no es un diccionario, solo una lista.

Otra idea puede ser abrir un nuevo ticket y cargar un parche con un nuevo parámetro dentro de settings.py :

AUTH_USER_EMAIL_UNIQUE = True

¿Alguna sugerencia sobre la forma más correcta de lograr la singularidad de la dirección de correo electrónico en el modelo de usuario de Django?


¡Es increíble, pero encontré la mejor solución para mí!

django-registration tiene forma con comprobación de la singularidad del campo de correo electrónico: RegistrationFormUniqueEmail

ejemplo de uso here


¿Qué tal usar unique_together de una manera "diferente"? Hasta ahora me funciona.

class User(AbstractUser): ... class Meta(object): unique_together = (''email'',)


Agrega un lugar como este:

User._meta.get_field_by_name(''email'')[0]._unique = True

y luego ejecuta SQL similar a esto:

ALTER TABLE auth_user ADD UNIQUE (email);


Agregue la función siguiente en cualquiera de los archivos models.py. Luego ejecute makemigrations y migre. Probado en Django1.7

def set_email_as_unique(): """ Sets the email field as unique=True in auth.User Model """ email_field = dict([(field.name, field) for field in MyUser._meta.fields])["email"] setattr(email_field, ''_unique'', True) #this is called here so that attribute can be set at the application load time set_email_as_unique()


Creo que la respuesta correcta aseguraría que la verificación de unicidad se colocara dentro de la base de datos (y no en el lado django). Debido a las condiciones de tiempo y carrera, puede terminar con correos electrónicos duplicados en la base de datos a pesar de tener pre_save que hace las comprobaciones adecuadas.

Si realmente lo necesitas mal, supongo que puedes intentar seguir este enfoque:

  1. Copie el modelo de usuario en su propia aplicación y cambie el correo electrónico de campo para que sea único.
  2. Registre este modelo de usuario en la aplicación de administración (usando la clase de administración de django.contrib.auth.admin )
  3. Cree su propio servidor de autenticación que use su modelo en lugar de django one.

Desde la versión 1.2 (11 de mayo de 2015), ha habido una forma de importar dinámicamente cualquier formulario de registro elegido mediante la opción de configuración REGISTRATION_FORM .

Entonces, uno podría usar algo como esto:

REGISTRATION_FORM = ''registration.forms.RegistrationFormUniqueEmail''

Esto está documentado here .

Y aquí está el enlace a la entrada del registro de cambios .


Django no permite la edición directa del objeto del usuario, pero puede agregar la señal pre_save y lograr un correo electrónico único. para crear señales, puede seguir https://docs.djangoproject.com/en/2.0/ref/signals/ . luego agrega lo siguiente a tus signals.py

@receiver(pre_save, sender=User) def check_email(sender,instance,**kwargs): try: usr = User.objects.get(email=instance.email) if usr.username == instance.username: pass else: raise Exception(''EmailExists'') except User.DoesNotExist: pass


Django tiene un ejemplo completo en su documentación sobre cómo sustituir y usar un modelo de usuario personalizado, por lo que puede agregar campos y usar el correo electrónico como nombre de usuario.


En el módulo de configuración:

# Fix: username length is too small,email must be unique from django.contrib.auth.models import User, models User._meta.local_fields[1].__dict__[''max_length''] = 75 User._meta.local_fields[4].__dict__[''_unique''] = True


Este método no hará que el campo de correo electrónico sea único en el nivel de la base de datos, pero vale la pena intentarlo.

Use un validator personalizado:

from django.core.exceptions import ValidationError from django.contrib.auth.models import User def validate_email_unique(value): exists = User.objects.filter(email=value) if exists: raise ValidationError("Email address %s already exists, must be unique" % value)

Luego en forms.py:

from django.contrib.auth.models import User from django.forms import ModelForm from main.validators import validate_email_unique class UserForm(ModelForm): #.... email = forms.CharField(required=True, validators=[validate_email_unique]) #....


Fui a /Lib/site-packages/django/contrib/auth/models y en la clase AbstractUser(AbstractBaseUser, PermissionsMixin): Cambié el correo electrónico para que fuera:

email = models.EmailField(_(''email address''), **unique=True**, blank=True)

Con esto, si intenta registrarse con una dirección de correo electrónico ya presente en la base de datos, recibirá un mensaje: El usuario con esta dirección de correo electrónico ya existe.


La primera respuesta aquí funciona para mí cuando estoy creando nuevos usuarios, pero falla cuando intento editar un usuario, ya que excluyo el nombre de usuario de la vista. ¿Existe una edición simple para esto que haga que la verificación sea independiente del campo de nombre de usuario?

También traté de incluir el campo de nombre de usuario como un campo oculto (ya que no quiero que la gente lo edite), pero eso también falló porque django estaba buscando nombres de usuario duplicados en el sistema.

(Lo siento, esto se publicó como una respuesta, pero me faltan las credenciales para publicarlo como comentario. No estoy seguro de entender la lógica de sobre eso).


Para garantizar que un usuario, sin importar dónde, se guarde con un correo electrónico único, agréguelo a sus modelos:

@receiver(pre_save, sender=User) def User_pre_save(sender, **kwargs): email = kwargs[''instance''].email username = kwargs[''instance''].username if not email: raise ValidationError("email required") if sender.objects.filter(email=email).exclude(username=username).count(): raise ValidationError("email needs to be unique")

Tenga en cuenta que esto asegura que el correo electrónico no esté en blanco también. Sin embargo, esto no valida los formularios como sería apropiado, solo plantea una excepción.


Puede usar su propio modelo de usuario personalizado para este propósito. Puede usar el correo electrónico como nombre de usuario o teléfono como nombre de usuario, puede tener más de un atributo.

En su settings.py necesita especificar la configuración siguiente AUTH_USER_MODEL = ''myapp.MyUser''.

Aquí está el enlace que puede ayudarte. https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#auth-custom-user


Tu forma debe verse más o menos así.

def clean_email(self): email = self.cleaned_data.get(''email'') username = self.cleaned_data.get(''username'') print User.objects.filter(email=email).count() if email and User.objects.filter(email=email).count() > 0: raise forms.ValidationError(u''This email address is already registered.'') return email


Una forma posible de hacerlo es tener un gancho guardado previamente en el objeto Usuario y rechazar el guardado del correo electrónico que ya existe en la tabla.


desde un modelo heredado por el usuario, redefina el atributo correctamente. Debería funcionar, ya que no es útil tenerlo en django core porque es simple de hacer.