69👍
Original answer, for Django < 1.7:
You can register the signals by importing signals.py
in the app’s __init__.py
file:
# __init__.py
import signals
This will allow to import models.py
from signals.py
without circular import errors.
One problem with this approach is that it messes up the coverage results if you’re using coverage.py.
Edit: For Django >= 1.7:
Since AppConfig was introduced, the recommended way of importing signals is in its init()
function. See Eric Marcos’ answer for more details.
230👍
If you’re using Django<=1.6 I’d recommend Kamagatos solution: just import your signals at the end of your models module.
For future versions of Django (>=1.7), the recommended way is to import your signals module in your app’s config ready() function:
my_app/apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
import my_app.signals
my_app/__init__.py
default_app_config = 'my_app.apps.MyAppConfig'
- [Django]-Phpmyadmin logs out after 1440 secs
- [Django]-How to delete project in django
- [Django]-Error: No module named staticfiles
27👍
To solve your problem you just have to import signals.py after your model definition. That’s all.
- [Django]-Pytest.mark.parametrize with django.test.SimpleTestCase
- [Django]-Add additional options to Django form select widget
- [Django]-How to compare two JSON objects with the same elements in a different order equal?
6👍
I also put signals in signals.py file and also have this code snippet that loads all signals:
# import this in url.py file !
import logging
from importlib import import_module
from django.conf import settings
logger = logging.getLogger(__name__)
signal_modules = {}
for app in settings.INSTALLED_APPS:
signals_module = '%s.signals' % app
try:
logger.debug('loading "%s" ..' % signals_module)
signal_modules[app] = import_module(signals_module)
except ImportError as e:
logger.warning(
'failed to import "%s", reason: %s' % (signals_module, str(e)))
This is for project, I’m not sure if it works at app level.
- [Django]-How to manually assign imagefield in Django
- [Django]-Django check for any exists for a query
- [Django]-How do you configure Django for simple development and deployment?
6👍
In old Django versions would be fine to put the signals on the __init__.py
or maybe in the models.py
(although at the end models will be way to large for my taste).
With Django 1.9, it is better I think, to place the signals on a signals.py
file and import them with the apps.py
, where they are going to be loaded after loading the model.
apps.py:
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = 'polls'
def ready(self):
from . import signals # NOQA
You can also divide your signals on signals.py
and handlers.py
in another folder within your model named signals
as well, but for me that is just over engineering. Take a look at Placing Signals
- [Django]-How to deal with "SubfieldBase has been deprecated. Use Field.from_db_value instead."
- [Django]-How do I access the request object or any other variable in a form's clean() method?
- [Django]-Manager isn't accessible via model instances
6👍
This only applies if you have your signals in a separate signals.py
file
In completely agree with the answer of @EricMarcos but it should be stated that the django docs explicitly advice not to use the default_app_config variable (although it is not wrong). For current versions, correct way would be:
my_app/apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
import my_app.signals
settings.py
(Make sure you don’t just have your app name in installed apps but instead the relative path to your AppConfig)
INSTALLED_APPS = [
'my_app.apps.MyAppConfig',
# ...
]
- [Django]-What's the recommended approach to resetting migration history using Django South?
- [Django]-ImportError: cannot import name '…' from partially initialized module '…' (most likely due to a circular import)
- [Django]-Why does django run everything twice?
4👍
I’m guessing that you’re doing that so your signals are registered, so that they’re found somewhere. I just put my signals right in a models.py file normally.
- [Django]-Django-Bower + Foundation 5 + SASS, How to configure?
- [Django]-Passing variable urlname to url tag in django template
- [Django]-Backwards migration with Django South
1👍
An alternative is to import the callback functions from signals.py
and connect them in models.py
:
signals.py
def pre_save_callback_function(sender, instance, **kwargs):
# Do stuff here
model.py
# Your imports here
from django.db.models.signals import pre_save
from yourapp.signals import pre_save_callback_function
class YourModel:
# Model stuff here
pre_save.connect(pre_save_callback_function, sender=YourModel)
Ps: Importing YourModel
in signals.py
will create a recursion; use sender
, instead.
Ps2: Saving the instance again in the callback function will create a recursion. You can make a control argument in .save
method to control it.
- [Django]-Allowing only super user login
- [Django]-Django: how save bytes object to models.FileField?
- [Django]-How to expire session due to inactivity in Django?