Entonces estoy usando un modelo de usuario personalizado

    from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class UserManager(BaseUserManager):
    def create_user(self, email, full_name, address, number, password=None):
        """
        Creates and saves a User with the given email and password.
        """
        if not email:
            raise ValueError('Users must have an email address')
        if not full_name:
            raise ValueError('Users must have an email address')
        if not address:
            raise ValueError('Users must have an email address')
        if not number:
            raise ValueError('Users must have an email address')
        if not password:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email.lower()),
            full_name=full_name,
            address = address,
            number=number,
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_staffuser(self, email, full_name, address, number, password):
        """
        Creates and saves a staff user with the given email and password.
        """
        user = self.create_user(
            email,
            full_name,
            address,
            numbe,
            password = password,
        )
        user.staff = True
        user.save(using=self._db)
        return user

    def create_superuser(self, email, full_name, address, number, password):
        """
        Creates and saves a superuser with the given email and password.
        """
        user = self.create_user(
            email,
            full_name,
            address,
            number,
            password = password,
        )
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user

class User(AbstractBaseUser):
    email = models.EmailField(max_length=255, unique=True)
    full_name = models.CharField(max_length=255, blank = False, null = False)
    address = models.CharField(max_length=255, blank = False, null = False)
    number = models.CharField(max_length=255, blank = False, null = False)
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) # a admin user; non super-user
    admin = models.BooleanField(default=False) # a superuser
    # notice the absence of a "Password field", that's built in.

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['full_name', 'address', 'number'] # Email & Password are required by default.

    objects = UserManager()

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __str__(self):              # __unicode__ on Python 2
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        return self.staff

    @property
    def is_admin(self):
        "Is the user a admin member?"
        return self.admin

    @property
    def is_active(self):
        "Is the user active?"
        return self.active

Este es mi admin.py para la aplicación.

    from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from .forms import UserAdminChangeForm, UserAdminCreationForm
from .models import User

class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserAdminChangeForm
    add_form = UserAdminCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('email', 'admin')
    list_filter = ('admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('full_name', 'address', 'number')}),
        ('Permissions', {'fields': ('admin', 'active', 'staff')}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'full_name', 'address', 'number', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()


admin.site.register(User, UserAdmin)
admin.site.unregister(Group)

Y finalmente formas.py

    from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField

from .models import User

class UserAdminCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
    fields, plus a repeated password."""
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('email', 'full_name', 'address', 'number')

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserAdminCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserAdminChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = User
        fields = ('email', 'full_name', 'address', 'number', 'password', 'active', 'admin')

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]

Por lo tanto, funciona muy bien cuando creo un superusuario a través de la consola con manage.py, pero cuando decido editar, eliminar o crear otro usuario en el panel de administración de la interfaz gráfica de usuario, aparece una "restricción de TECLA EXTRANJERA fallida". Lo que no entiendo, ¿alguien podría señalarme en la dirección correcta?

0
Frectul 1 mar. 2018 a las 19:30

3 respuestas

La mejor respuesta

Pregunté y el código debería funcionar en versiones anteriores de django. Lamentablemente, no funcionará en django 2.0 o superior. Si alguien quiere una alternativa, encontré esto para ser perfecto para mi proyecto, la explicación también es simple.

1
Frectul 2 mar. 2018 a las 15:30

Para django 2.2+:

  1. Si se trata de datos de prueba -> entonces debe eliminar todas las migraciones y carpetas de pycache de todas las aplicaciones y proyectos y eliminar también el archivo 'db.sqlite3'.
  2. Realice migraciones y migre aplicaciones, entonces funciona. (Tengo los mismos problemas y funcionó con este método).
  3. Si los datos se importan, puede hacer una copia de seguridad de los datos fácilmente utilizando los accesorios de Google.
0
PrakashG 26 jun. 2019 a las 11:58

Creo que he encontrado una solución para esto. El problema podría deberse a problemas de dependencias circulares cuando migra su AUTH_USER_MODEL predeterminado a un modelo personalizado en el medio del proyecto.

De la documentación de Django

Cambiar AUTH_USER_MODEL después de haber creado tablas de bases de datos es significativamente más difícil, ya que afecta a claves externas y relaciones de muchos a muchos, por ejemplo.

Este cambio no se puede hacer automáticamente y requiere corregir manualmente su esquema, mover sus datos de la tabla de usuario anterior y posiblemente volver a aplicar manualmente algunas migraciones. Ver # 25313 para un resumen de los pasos.

Debido a las limitaciones de la característica de dependencia dinámica de Django para los modelos intercambiables, el modelo al que hace referencia AUTH_USER_MODEL debe crearse en la primera migración de su aplicación (generalmente llamada 0001_initial); de lo contrario, tendrá problemas de dependencia.

Además, puede encontrarse con un CircularDependencyError cuando ejecute sus migraciones, ya que Django no podrá romper automáticamente el bucle de dependencia debido a la dependencia dinámica. Si ve este error, debe romper el ciclo moviendo los modelos de los que depende su modelo de usuario a una segunda migración. (Puede intentar hacer dos modelos normales que tengan una ForeignKey entre sí y ver cómo makemigrations resuelve esa dependencia circular si desea ver cómo se hace generalmente).

La mejor manera de abordar esto es soltar la tabla y eliminar todos los archivos de migración y luego volver a ejecutar las migraciones con su modelo personalizado recién creado. Espero que esto funcione.

Puede encontrar más detalles sobre cómo migrar de un modelo integrado a un nuevo modelo aquí https: // code .djangoproject.com / ticket / 25313

2
Jishnu R 5 may. 2018 a las 10:32