python - 仅生产中的 AUTH_USER_MODEL 错误:AUTH_USER_MODEL 指的是尚未安装的模型“auth.User”
问题描述
我的应用程序在 localhost 上运行,但是当我部署到生产环境(Heroku)时,出现此错误:
File "./blog/models.py", line 6, in <module>
2021-03-24T23:31:05.696194+00:00 app[web.1]: User = get_user_model()
2021-03-24T23:31:05.696219+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/django/contrib/auth/__init__.py", line 162, in get_user_model
2021-03-24T23:31:05.696372+00:00 app[web.1]: "AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL
2021-03-24T23:31:05.696397+00:00 app[web.1]: django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.User' that has not been installed
我尝试了无数的配置,例如在设置AUTH_USER_MODEL = 'auth.User'
中设置from django.contrib.auth.models import User
和:
from django.contrib.auth import get_user_model
User = get_user_model()
但没有任何效果。
设置.py
"""~~~NOTES~~~
- procfile could use channel_layer instead of channels
- AUTH_USER_MODEL could be 'django_project.User'. Worked locally but not on heroku
- django.setup() seems ok at bottom of settings.py
- If have to
"""
import django
from django.core.wsgi import get_wsgi_application
from django.core.asgi import get_asgi_application
# from django.contrib.auth.models import User #todo: this causes ImproperlyConfigured: SECRET_KEY MUST NOT BE EMPTY
import os
import django_heroku
DJANGO_SETTINGS_MODULE = 'django_project.settings'
SECRET_KEY = 'asdaf123$9pv98=e6p^gl(-eoj' #todo: test removing this in own deployment
# AUTH_USER_MODEL=User # todo: this causes RuntimeError: populate() isnt reentrant
#SECRET_KEY = os.environ.get('SECRET_KEY')
DEBUG = 'True'
ALLOWED_HOSTS = ['*', 'localhost', '127.0.0.1']
INSTALLED_APPS = [
'django.contrib.auth',
'blog.apps.BlogConfig', #allows Django to correctly search your templates for the 'blog' app
'users.apps.UsersConfig',
# 'chat.apps.ChatConfig',
'chat',
'crispy_forms',
'channels',
'dal',
'dal_select2',
'django.contrib.admin',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
# 'django_messages',
'django.contrib.staticfiles',
'storages'
]
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',
]
ROOT_URLCONF = 'django_project.urls'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, '')],
'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',
],
# 'libraries': {
# 'staticfiles':'chat.templatetags.__init__.py'
# }
},
},
]
SETTINGS_PATH = os.path.join(os.path.dirname(__file__) ,'../templates').replace('\\','/')
TEMPLATE_DIRS = ( # deprecated
os.path.join(SETTINGS_PATH, 'blog/templates'), # Django will look at the templates from templates/ directory under your project
)
# ~~~MESSAGES CONFIG~~~
WSGI_APPLICATION = 'django_project.wsgi.application'
ASGI_APPLICATION = 'django_project.asgi.application' # older version of django: 'django_project.routing.application'
# Channels redis config:
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
#"hosts": [('127.0.0.1', 6379)], or 'redis' #l ocal
"hosts": ['rediss://:p628bf20dab326cedb30d4df129e9691dbb6e7e1f4486954eadbfdf77db854369@ec2-34-235-242-69.compute-1.amazonaws.com:25180'], # REDIS_TLS_URL #todo: confirm. Changed from "127.0.0.1" to 'redis'... found promising answer, changing this
# 'redis://:p628bf20dab326cedb30d4df129e9691dbb6e7e1f4486954eadbfdf77db854369@ec2-34-235-242-69.compute-1.amazonaws.com:25179' REDIS_URL
},
# "ROUTING": "chat.routing.websocket_urlpatterns", #todo: add "ROUTING": "chat.routing.websocket_urlpatterns",
},
}
CACHES = {
"default": {
"BACKEND": "redis_cache.RedisCache",
"LOCATION": os.environ.get('REDIS_TLS_URL'),
"OPTIONS": {
"CONNECTION_POOL_KWARGS": {
"ssl_cert_reqs": False
}
}
}
}
DATABASES = { # Use this to use local test DB
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
DB_URL = os.environ['DATABASE_URL']
DATABASE_URL = DB_URL
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',
},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'America/Los_Angeles'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
CRISPY_TEMPLATE_PACK = 'bootstrap4'
LOGIN_REDIRECT_URL = 'blog-home'
LOGIN_URL = 'login'
django_heroku.settings(locals())
DATA_UPLOAD_MAX_NUMBER_FIELDS = 4000
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'staticfilescustom') #todo: may have to add own staticFileDir folder
]
django.setup()
博客/模型(这是错误抱怨的地方):
from django.db import models
from django.utils import timezone
from django.contrib.auth import get_user_model
User = get_user_model()
from django.conf import settings
from django.urls import reverse
from datetime import datetime, timedelta
# we're inheriting from the models.Model
class Post(models.Model):
title = models.CharField(max_length=100) # character field
content = models.TextField() # Unrestricted text
date_posted = models.DateTimeField(default=timezone.now)
last_modified = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Game(models.Model):
name = models.TextField() # Unrestricted text
platform = models.CharField(max_length=100) # character field
created_date = models.DateTimeField(default=timezone.now)
name_and_platform = models.TextField(default='N/A') #todo: find a good max char limit
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name # return game name when game.objects.all() is called
def get_name_and_platform(self):
return ''.join([self.name, '(', self.platform, ')'])
def save(self, *args, **kwargs):
self.name_and_platform = self.get_name_and_platform()
super(Game, self).save(*args, **kwargs)
class Trade(models.Model):
name = models.TextField() # Unrestricted text
created_date = models.DateTimeField(default=timezone.now)
is_trade_proposed = models.BooleanField(default=False)
user_who_posted = models.ForeignKey(User, on_delete=models.CASCADE)
owned_game = models.ForeignKey(Game, on_delete=models.CASCADE, related_name='owned_game', db_column='owned_game')
desired_game = models.ForeignKey(Game, on_delete=models.CASCADE, related_name='desired_game', db_column='desired_game')
def get_trade_name(self):
return ''.join([self.user_who_posted.username, '(', timezone.now().strftime("%b %d, %Y %H:%M:%S UTC"), ')'])
def save(self, *args, **kwargs):
self.name = self.get_trade_name()
super(Trade, self).save(*args, **kwargs)
def __str__(self):
return self.name # return game name when game.objects.all() is called
class Transaction(models.Model):
name = models.TextField() # Unrestricted text
created_date = models.DateTimeField(default=timezone.now)
trade_one = models.ForeignKey(Trade, on_delete=models.CASCADE, related_name='trade_one', db_column='trade_one')
trade_two = models.ForeignKey(Trade, on_delete=models.CASCADE, related_name='trade_two', db_column='trade_two')
status = models.TextField() # Unrestricted text. Validated in form.
expiry_date = models.DateTimeField(default=datetime.today() + timedelta(days=3))
open_expiry_date = models.DateTimeField(default=datetime.today() + timedelta(days=9))
user_cancelled_date = models.DateTimeField(null=True, blank=True)
def get_transaction_name(self):
return ''.join([str(self.trade_one_id), ' and ', str(self.trade_two_id), ' on ', timezone.now().strftime("%b %d, %Y %H:%M:%S UTC"), ''])
def get_status_on_insert(self):
return 'Waiting for 2nd confirmation from ' + str(self.trade_two.user_who_posted)
def save(self, *args, **kwargs):
if self.name == '':
self.name = self.get_transaction_name()
if self.status == '':
self.status = self.get_status_on_insert()
super(Transaction, self).save(*args, **kwargs)
def __str__(self):
return self.name # return name when game.objects.all() is called
def get_absolute_url(self): #todo: remove?
return reverse('confirmed-trade', kwargs={'pk': self.pk})
聊天/models.py
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
# from django.conf import settings
from django.utils import timezone
class Message(models.Model):
author = models.ForeignKey(User, related_name='author_messages', on_delete=models.CASCADE)
content = models.TextField()
timestamp = models.DateTimeField(default=timezone.now) #todo: timezone fix?
def __str__(self):
return self.author.username
def last_10_messages(self):
return Message.objects.order_by('-timestamp').all()[:10] # only load last x msgs from DB
用户/模型.py
from django.db import models
from PIL import Image
from django.contrib.auth import get_user_model
User = get_user_model()
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
聊天/consumers.py
# chat/consumers.py
import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from .models import Message
from django.contrib.auth import get_user_model
User = get_user_model()
from django.conf import settings
class ChatConsumer(WebsocketConsumer):
def fetch_messages(self, data):
print('~~~fetch_messages~~~')
messages = Message.last_10_messages(self)
content = {
'command': 'messages',
'messages': self.messages_to_json(messages)
}
print('content: ' + str(content))
self.send_message(content)
def new_message(self, data):
print('~~~in new_message: 2~~~')
author = data['from']
print('author: ' + author)
author_user = User.objects.filter(username=author)[0]
message = Message.objects.create(author=author_user, content=data['message'])
content = {
'command': 'new_message',
'message': self.message_to_json(message)
}
return self.send_chat_message(content)
def messages_to_json(self, messages):
print('~~~messages_to_json~~~')
result = []
for message in messages:
result.append(self.message_to_json(message))
return result
def message_to_json(self, message):
print('~~~message_to_json~~~')
return {
'author': message.author.username,
'content': message.content,
'timestamp': str(message.timestamp)
}
commands = {
'fetch_messages': fetch_messages,
'new_message': new_message
}
def connect(self):
print('~~~connect~~~')
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
self.accept()
def disconnect(self, close_code):
print('~~~disconnect~~~')
# Leave room group
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
def receive(self, text_data):
print('~~~receive: 1~~~')
data = json.loads(text_data)
self.commands[data['command']](self, data) # either fetch_messages or new_message
def send_chat_message(self, message):
print('in send_chat_message: 3')
async_to_sync(self.channel_layer.group_send)( # Send message to room group
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
def send_message(self, message):
self.send(text_data=json.dumps(message))
# Receive message from room group
def chat_message(self, event):
message = event['message']
print('message: ' + str(message))
content1 = message['message']
print('content1: ' + str(content1))
content2 = content1['content']
print('content2: ' + content2)
self.send(text_data=json.dumps(message)) # Send message to WebSocket
~~~~~~~~~更新:~~~~~~~~~当我从
release: python manage.py migrate
web: daphne django_project.asgi:application --port $PORST --bind 0.0.0.0 v2
worker: python manage.py runworker channel_layer --settings=django_project.settigns -v2
至
web: gunicorn django_project.wsgi
我的应用程序成功构建!为什么我的 procfile 会导致该错误?
解决方案
推荐阅读
- r - 如何指定我想要 R 中的“按顺序添加”线性回归?
- javascript - 如何从firebase禁用用户?
- python - 来自文件路径的文件夹和文件名的 sqlalchemy @hybrid_property 表达式。很容易用纯python编写
- here-api - Here.com API 格式
- excel - 从 Excel 实例更新 Powerpoint 图表数据 - 编辑数据时数据消失
- typescript - 如何在 redux-toolkit 上正确键入 NormalizedSchema 作为 PayloadAction?
- coefficients - 泰勒级数展开最大值
- ios - 无法将集合视图中的单个单元格出列
- python - 使用 PySpark 将许多小型 csv 文件(130,000 个,每个 2 列)有效地组合到一个大框架中
- java - 在 Java 中使用线程的并行素数检查器