You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django 4 admin报错:User模型未注册,如何为默认User关联Address?

解决Django 4中默认User模型添加Address内联时的「The model User is not registered」错误

问题描述

尝试在Django 4的admin视图中为默认User模型(非自定义模型)关联Address模块,该操作在Django 2中可正常运行,但在Django 4中执行时出现「The model User is not registered」错误。

相关代码文件

models.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}'

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)

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'

错误原因

Django 4调整了app的加载顺序逻辑,你的自定义appacme_nft_app在INSTALLED_APPS中排在django.contrib.admin之前,导致执行admin.site.unregister(User)时,默认User模型还未被admin模块注册,因此抛出「The model User is not registered」错误。

解决方案

方案一:调整INSTALLED_APPS顺序

将django.contrib.admin移到你的自定义app之前,确保admin模块先加载并注册User模型:

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

方案二:继承默认UserAdmin并安全注销

不需要直接使用admin.ModelAdmin,而是继承Django默认的UserAdmin类,同时添加注销前的检查,避免未注册时的报错:
修改admin.py如下,同时修正原代码中AddresInline的拼写错误(应为AddressInline):

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DefaultUserAdmin
from django.contrib.auth.models import User

from .models import Product, ProductEntry, Opinion, Address


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

class CustomUserAdmin(DefaultUserAdmin):
    # 保留默认UserAdmin的所有配置,添加Address内联
    inlines = DefaultUserAdmin.inlines + [AddressInline]

# 先检查User是否已注册,再执行注销
if User in admin.site._registry:
    admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

# 注册其他模型
admin.site.register(Product)
admin.site.register(ProductEntry)
admin.site.register(Opinion)

额外注意

原代码中AddresInline存在拼写错误,少了一个字母s,修正为AddressInline可避免后续可能出现的视图加载错误。

内容的提问来源于stack exchange,提问作者Vicente

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:55:31