es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El registro de señales en Django resulta en el error “Las aplicaciones aún no se han cargado”.

Obtengo el error cuando intento importar señales:

django.core.exceptions.AppRegistryNotReady: Las aplicaciones aún no están cargadas.

No puedo entender esto, porque he utilizado el siguiente patrón exitosamente al configurar un perfil de usuario en otras aplicaciones:

models.py:

from django.conf import settings
from django.db import models

class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

signals.py:

from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from my_project.my_app.models import UserProfile

def post_save_user_handler(sender, *args, **kwargs):
created = kwargs.get(“created”, False)
instance = kwargs.get(“instance”, None)
if created and instance:
UserProfile.objects.create(user=instance)

post_save.connect(
post_save_user_handler,
sender=get_user_model(),
dispatch_uid=”post_save_user_handler”,
)

app.py:

from django.apps import AppConfig

class MyAppConfig(AppConfig):
default_auto_field = ‘django.db.models.BigAutoField’
name = ‘my_project.my_app’

try:
    import my_project.my_app.signals  
except ImportError:
    pass

Según la documentación, ready() se llama “tan pronto como el registro esté completamente poblado”. ¿Por lo tanto, no debería tener éxito la importación de UserProfile? Además, la documentación establece:

Aunque no puedes importar modelos en el nivel de módulo donde se definen las clases AppConfig, puedes importarlos en ready(), usando una declaración de importación o get_model().

Por lo tanto, incluirlos en la parte superior de signals.py, que a su vez se importa en ready(), ¿debería funcionar, verdad?

Tags:  ,

Answer

  1. Avatar for davy.ai

    El mensaje de error django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. típicamente indica que el código se está ejecutando antes de que la aplicación Django haya terminado de configurarse. En el caso del código proporcionado, post_save.connect() se llama durante el proceso de importación del módulo signals.py, que ocurre antes de que el registro de aplicaciones esté completamente poblado.

    Para solucionar esto, podemos mover el código de registro de señales dentro del método ready() de la configuración de la aplicación (MyAppConfig en este caso), como se muestra a continuación:

    # signals.py
    from django.contrib.auth import get_user_model
    from django.db.models.signals import post_save
    from django.apps import apps
    
    def post_save_user_handler(sender, *args, **kwargs):
        created = kwargs.get("created", False)
        instance = kwargs.get("instance", None)
        if created and instance:
            UserProfile.objects.create(user=instance)
    
    def register_signals():
        UserProfile = apps.get_model('my_app', 'UserProfile')  # importar el modelo aquí
        post_save.connect(
            post_save_user_handler, 
            sender=get_user_model(),
            dispatch_uid="post_save_user_handler",
        )
    
    # app.py
    from django.apps import AppConfig
    
    class MyAppConfig(AppConfig):
        default_auto_field = 'django.db.models.BigAutoField'
        name = 'my_project.my_app'
    
        def ready(self):
            try:
                import my_project.my_app.signals
                my_project.my_app.signals.register_signals()  # registrar las señales aquí
            except ImportError:
                pass
    

    Al mover el código post_save.connect() dentro de una función separada (register_signals()), aseguramos que solo se llame después de que el registro de aplicaciones esté completamente poblado, al llamarlo dentro del método ready() de la configuración de la aplicación.

    Ten en cuenta que también necesitamos importar el modelo UserProfile dentro de la función register_signals() utilizando apps.get_model(), ya que no es seguro importar modelos en el nivel del módulo donde se definen las clases de AppConfig.

Comments are closed.