Foros del Web » Programando para Internet » Python »

[SOLUCIONADO] Modelo usuario personalizado y migraciones

Estas en el tema de Modelo usuario personalizado y migraciones en el foro de Python en Foros del Web. Hola, estoy intentando usar un modelo usuario personalizado en la autenticación de django (a recomendacion de usuarios de este mismo foro en hilos anteriores) y ...
  #1 (permalink)  
Antiguo 06/11/2013, 05:55
Avatar de jhg
jhg
 
Fecha de Ingreso: marzo-2012
Mensajes: 96
Antigüedad: 12 años
Puntos: 1
Modelo usuario personalizado y migraciones

Hola, estoy intentando usar un modelo usuario personalizado en la autenticación de django (a recomendacion de usuarios de este mismo foro en hilos anteriores) y ahora la duda que tengo es con las migraciones (con south).

Estoy acostumbrado a primero hacer un syncdb luego los migrate apropiados pero ahora tengo duda de si podre usarlas con el modelo personalizado por como hasta hacer el migrate me imagino no llegara el modelo a estar en la base de datos pero el primer syncdb me pedira crear un superusuario, o eso creo, entonces no se si podria funcionar, etc. Como me surgio esta duda aunque tengo (o eso creo) preparado todo para usar el modelo personalizado aun no he hecho el syncdb ni he iniciado las migraciones para consultar esto a ver si alguien con más experiencia sabe algo al respecto de esto, antes de que falle algo y acabe sin saber si falla por las migraciones, por que este mal el modelo personalizado, por que este mal configurado, etc; y al final no saber ni donde he metido la pata.

En el settings añadi el middleware para que funcione la autenticacion:
'django.contrib.auth.middleware.AuthenticationMidd leware'
Y la aplicacion:
'django.contrib.auth'
Y por supuesto indique el modelo personalizado:
AUTH_USER_MODEL = 'piktul.User'

Y el modelo personalizado:
Código:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.core.mail import send_mail
from django.contrib.auth.signals import user_logged_in


def update_last_login(sender, user, **kwargs):
    """
    A signal receiver which updates the last_login date for
    the user logging in.
    """
    user.last_login = timezone.now()
    user.save(update_fields=['last_login'])
user_logged_in.connect(update_last_login)

class UserManager(BaseUserManager):

    def _create_user(self, email, password,
                     is_staff, is_superuser, **extra_fields):
        """
        Creates and saves a User with the given email and password.
        """
        now = timezone.now()
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email,
                          is_staff=is_staff, is_active=True,
                          is_superuser=is_superuser, last_login=now,
                          date_joined=now, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        return self._create_user(email, password, False, False,
                                 **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        return self._create_user(username, email, password, True, True,
                                 **extra_fields)

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), max_length=254,
                              unique=True, db_index=True, blank=True)
    is_staff = models.BooleanField(_('staff status'), default=False,
        help_text=_('Designates whether the user can log into this admin '
                    'site.'))
    is_active = models.BooleanField(_('active'), default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def get_full_name(self):
        return getattr(self, self.USERNAME_FIELD)

    def get_short_name(self):
        return getattr(self, self.USERNAME_FIELD)

    def email_user(self, subject, message, from_email=None, **kwargs):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email], **kwargs)

    def __str__(self):
        return self.email

    def __unicode__(self):
        return self.email
El proyecto lo estoy ejecutando sobre Python3, las migraciones con otros modelos las he probado y fucionan bien, pero este por lo que comentaba de en el primer syncdb pedir un superusuario no se si podre usarlas o como debo hacerlo por lo menos en la primera vez.
__________________
JHG
  #2 (permalink)  
Antiguo 06/11/2013, 12:47
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 1 mes
Puntos: 1360
Respuesta: Modelo usuario personalizado y migraciones

Recomendaciones:

1. Hacer un respaldo tanto del código como de la db.
2. Hacer cambios en el modelo.
3. Aplicar migraciones.
4. Si algo falla haces un rollback del código y de los datos en la db.
  #3 (permalink)  
Antiguo 06/11/2013, 17:11
Avatar de jhg
jhg
 
Fecha de Ingreso: marzo-2012
Mensajes: 96
Antigüedad: 12 años
Puntos: 1
Respuesta: Modelo usuario personalizado y migraciones

De que sean recomendaciones tipo por probar entiendo que debo ser de los primeros que han intentado tan arriesgada mezcla jejeje.

La duda que tengo es si inicio las migraciones y hago primero el migrate del modelo de usuario y luego el syncdb para que cuando me pida crear el superusuario funcione o si el intentar hacer esto hara que luego quede algo inestable del tipo que no se ve a simple vista y lo descubres cuando al tocar algo más se termina de quedar todo inservible.

Respaldar el codigo, con git con una nueva rama para probar a lo loco creo que es suficiente, la base de datos... la que tengo en produccion no tengo animos de intentarlo, es postgresql y yo anteriormente la mysql si la he usado, postgresql la he usado poco y más bien estoy aun aprendiendo, en local para desarrollo tengo sqlite pero en local estoy con python2, las migraciones las modifico para quitarles la u delante de las cadenas y con eso quedan migradas las migraciones jejeje.

Voy a hacer café y intentar a ver que sale...
__________________
JHG
  #4 (permalink)  
Antiguo 11/11/2013, 06:21
Avatar de jhg
jhg
 
Fecha de Ingreso: marzo-2012
Mensajes: 96
Antigüedad: 12 años
Puntos: 1
Respuesta: Modelo usuario personalizado y migraciones

Hola, haciendo pruebas durante el fin de semana resulta que hacer una migracion antes del syncdb es imposible pero el syncdb no intento crear un superusuario, me dio tiempo de hacer la migracion seguidamente y el problema viene al intentar crear el superusuario con el comando django createsuperuser que da este error:

NameError: global name 'username' is not defined

He mirado en github el codigo de createsuperuser para ver si veo que ha podido pasar, he revisado mi modelo, pero al menos de momento no se me ocurre nada, en el modelo no uso username pero indico que el campo de nombre de usuario es el campo email, y username en createsuperuser es una variable que por lo que creo entnedi recoge el campo que se indica como nombre de usuario.

Creo que la parte del createsuperuser donde se para es en:
user_data[self.UserModel.USERNAME_FIELD] = username

Pues todo lo anterior si lo hace de pedirme el email, la clave, etc.

El codigo del modelo:
Código:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.core.mail import send_mail
from django.contrib.auth.signals import user_logged_in


def update_last_login(sender, user, **kwargs):
    """
    A signal receiver which updates the last_login date for
    the user logging in.
    """
    user.last_login = timezone.now()
    user.save(update_fields=['last_login'])
user_logged_in.connect(update_last_login)

class UserManager(BaseUserManager):

    def _create_user(self, email, password,
                     is_staff, is_superuser, **extra_fields):
        """
        Creates and saves a User with the given email and password.
        """
        now = timezone.now()
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email,
                          is_staff=is_staff, is_active=True,
                          is_superuser=is_superuser, last_login=now,
                          date_joined=now, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        return self._create_user(email, password, False, False,
                                 **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        return self._create_user(username, email, password, True, True,
                                 **extra_fields)

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), max_length=254,
                              unique=True, db_index=True, blank=True)
    is_staff = models.BooleanField(_('staff status'), default=False,
        help_text=_('Designates whether the user can log into this admin '
                    'site.'))
    is_active = models.BooleanField(_('active'), default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def get_full_name(self):
        return getattr(self, self.USERNAME_FIELD)

    def get_short_name(self):
        return getattr(self, self.USERNAME_FIELD)

    def email_user(self, subject, message, from_email=None, **kwargs):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email], **kwargs)

    def __str__(self):
        return self.email

    def __unicode__(self):
        return self.email
__________________
JHG

Última edición por jhg; 11/11/2013 a las 06:23 Razón: Con la tonteria del captcha luego no salia la web tuve que dar atras y desaparecio el codigo final

Etiquetas: django
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 03:46.