Search code examples
djangodjango-admindjango-usersdjango-4.0

The model User is not registered (django-4 admin.py)


I'm trying to give User (django's default, not custom model) an Address in the admin view. I am working for the first time with different versions of django in different projects, I do the same in Django 2 and it works, and here I use Django 4.

This is my model.py:

from django.contrib.auth.models import User
from django.db import models
from enum import Enum

# Enum
class EntryType(Enum):
    cart = 'CART'
    order = 'ORDER'
    wishlist = 'WISHLIST'

class PaymentMethod(Enum):
    cash_on_delivery = 'CASH_ON_DELIVERY'
    card = 'CARD'

class Status(Enum):
    received = 'RECEIVED'
    sent = 'SENT'
    on_transit = 'ON_TRANSIT'
    delivered = 'DELIVERED'
    
class RarityType(models.TextChoices):
    common = 'COMMON'
    rare = 'RARE'
    epic = 'EPIC'
    legendary = 'LEGENDARY'
    mythic = 'MYTHIC'

# Models.

class Address(models.Model):
    street_name = models.CharField(max_length=60)
    number = models.IntegerField()
    block = models.IntegerField(null=True)
    floor = models.IntegerField(null=True)
    door = models.CharField(max_length=1, blank=True)
    city = models.CharField(max_length=60)
    code_postal = models.IntegerField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.street_name + ", " + str(self.number) + ", Bloque " + str(self.block) + ", " + str(self.floor) + "º " + self.door + ", " + self.city + ", " + str(self.code_postal)


class Complaint(models.Model):
    title = models.CharField(max_length=60)
    description = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    def __str__(self):
        return self.title

class Author(models.Model):
    name = models.CharField(max_length=60, unique=True)

    def __str__(self):
        return self.name

class Product(models.Model):
        
    name = models.CharField(max_length=60)
    collection = models.TextField()
    price = models.FloatField()
    stock = models.IntegerField()
    image_url = models.CharField(max_length=255, blank=True)
    offer_price = models.FloatField(blank=True, null=True)
    rarity = models.CharField(max_length=60, choices=[ (rarity, rarity.value) for rarity in RarityType], default=RarityType.common)
    author = models.ForeignKey(Author, on_delete=models.DO_NOTHING, null=True)
    
    def __str__(self):
        return self.name
class Opinion(models.Model):
    text = models.CharField(max_length=2000)
    date = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    def __str__(self):
        return self.text


class Order(models.Model):
    ref_code = models.CharField(max_length=60)
    payment_method = models.CharField(max_length=60, choices=[ (tag, tag.value) for tag in PaymentMethod])
    date = models.DateTimeField(auto_now_add=True)
    address = models.CharField(max_length=256)
    status = models.CharField(max_length=60, choices=[ (tag, tag.value) for tag in Status])
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.ref_code

class ProductEntry(models.Model):
    quantity = models.IntegerField(null=True)
    entry_type = models.CharField(max_length=60, choices=[ (tag, tag.value) for tag in EntryType])
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True)

    def __str__(self):
        return f'user_id: {self.user.id}, product_id: {self.product.id}, entry_type: {self.entry_type}'

This is my admin.py:

from django.contrib import admin
from django.contrib.auth.models import User

from .models import Product, ProductEntry, EntryType, Opinion, Address


# Register your models here.

class AddresInline(admin.TabularInline):
    model = Address
    extra = 1

class UserAdmin(admin.ModelAdmin):
    inlines = [AddresInline]


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

And last, settings.py:

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-5d%41lz3=u+rz@sr*pkcos65bgte-=abw!kog0g11uk0gqrnj6'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']


# Application definition

INSTALLED_APPS = [
    'acme_nft_app.apps.AcmeNftConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'livereload',
    'mathfilters'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'livereload.middleware.LiveReloadScript',
]

ROOT_URLCONF = 'acme_nft.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'acme_nft.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'acme_nft_db',
        'USER': 'acme',
        'PASSWORD': 'acme',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Working with django's user model (not custom model), I first unregister User and re-add it with the UserAdmin.


Solution

  • The INSTALLED_APPS were misordered.

    I had it like this:

    INSTALLED_APPS = [
    'acme_nft_app.apps.AcmeNftConfig', #From
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'livereload',
    'mathfilters']
    

    But my app should be after django defaults:

    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'acme_nft_app.apps.AcmeNftConfig', #To
    'livereload',
    'mathfilters']