from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
#receiver(post_save, sender=User)
def create_profile(receiver, instance, created, **kwargs):
if created:
Profile.objects.create(User=instance)
#receiver(post_save, sender=User)
def save_profile(receiver, instance, **kwargs):
instance.Profile.save()
apps.py
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
Error in server
File "C:\Users\Mian.G\Desktop\django_admin\users\apps.py", line 7, in
ready
import users.signals ModuleNotFoundError: No module named 'users.signals'
You've probably already solved this, as I see the post is almost 2 months old. But just in case you haven't.....is it possible you have created the 'signals.py' file in the 'users' sub directory instead of the 'users' root directory? I know from your code snippet that I am following the same tutorial and I was getting the same error because I hadn't created the 'signals.py' file in the 'users' app directory, but rather in the 'users' sub directory. If your 'signals.py' file is in the 'users' folder containing only 4 HTML files (login, logout, profile, register) then it is in the wrong location. Move it to the 'users' app directory and problem solved.
Related
ImportError: cannot import name 'Users' from partially initialized module 'users.models
from .models import Users
from celery import shared_task
from django.core.mail import send_mail
from server import settings
#shared_task()
def send_mail_task(user_id):
user = Users.objects.get(id=user_id)
send_mail(
subject='Congratulations!',
message=f'Congratulations {user.username}',
from_email=settings.EMAIL_HOST_USER,
recipient_list=["waelelsafty07#gmail.com", ],
fail_silently=False,
)
print('Email sent successfully')
return f'Email sent successfully'
checking installing celery
I import my model in this way:
model = apps.get_model(app_label='users', model_name='users')
when the users is name the folder
could you post your working directory so i can see where is the files are
if you didnt customize the user model then use
from django.contrib.auth.models import User
Django 3.0.5.
apps.py
from django.apps import AppConfig
from django.db.models.signals import post_save
from django.dispatch import receiver
class NewsConfig(AppConfig):
name = 'news'
def ready(self):
from .models import News # Breakpoint 0
#receiver(post_save, sender=News)
def handle_news_save(sender, **kwargs):
print("Working")
a = 0 # Breakpoint 1
models.py
class News(models.Model):
news_text = models.TextField()
settings.py
INSTALLED_APPS = [
...
'news.apps.NewsConfig',
]
The problem
At Breakpoint 0 the interpreter stops when I run the application. That is at the next line Django gets to know that I'm catching the signal.
But when I save an instance of News in admin site, at Breakpoint 1 the interpreter doesn't stop. And, of course, no printing happens.
Could you help me catch the signal?
Ok i tried it out and played with signals a little, here's what i found out:
As the question state this way of defining does not work it seems to not register the signal correctly. I have no clue why it doesn't.
I guess the convention about signals would be anyways to move them to a signals.py file and then in the apps.py you only import them.
signals.py:
from .models import News # Breakpoint 0
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=News)
def handle_news_save(sender, **kwargs):
print("Working")
a = 0 # Breakpoint 1
apps.py:
from django.apps import AppConfig
from django.db.models.signals import post_save
from django.dispatch import receiver
class PollsConfig(AppConfig):
name = 'polls'
def ready(self):
import polls.signals
and then it works
I am trying to implement signals for my app and my directory structure looks like this
- src
- utility_apps
__init__.py
- posts
- migrations
- static
- templates
admin.py
views.py
apps.py
signals.py
models.py
__init__.py
......
static
manage.py
......
Here posts is my app and the signals.py is inside its folder, But my signals aren't working.
I have defined my signal code as -
from .models import Post
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=Post)
def give_group_owner_permission(sender, instance, created, **kwargs):
print("coming to signal")
if created:
print("created")
But it doesn't work. In my apps.py I have changed the ready function as
class Post(AppConfig):
name = 'post'
def ready(self):
import utility_apps.posts.signals
I have even tried importing posts.signal in the ready function. What I am doing wrong here, please help
My installed apps look like below
INSTALLED_APPS = [
'utility_apps.posts',
'mainapp',
.....
]
The following solution worked for me.
The first change which I had to make was put a default_app_config value in my __init__.py file of my posts app as
default_app_config = 'utility_apps.posts.apps.PostsConfig'
And then I had to change PostsConfig class as
class PostsConfig(AppConfig):
name = 'utility_apps.posts'
def ready(self):
import utility_apps.posts.signals
Basically I had to change two things -
The name which was set to posts by default
Change the ready function and import my signals in it
It worked for me.
Alternatively, I could have also included my PostsConfig in my installed app.
Based on Django's documentation I was reading, it seems like signals.py in the app folder is a good place to start with, but the problem I'm facing is that when I create signals for pre_save and I try to import the class from model it conflicts with the import in my model.
# models.py
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import gettext as _
from signals import *
class Comm_Queue(CommunicatorAbstract):
queue_statuses = (
('P', _('Pending')),
('S', _('Sent')),
('E', _('Error')),
('R', _('Rejected')),
)
status = models.CharField(max_length=10, db_index=True, default='P')
is_html = models.BooleanField(default=False)
language = models.CharField(max_length=6, choices=settings.LANGUAGES)
sender_email = models.EmailField()
recipient_email = models.EmailField()
subject = models.CharField(max_length=100)
content = models.TextField()
# signals.py
from django.conf import settings
from django.db.models.signals import pre_save
from django.dispatch import receiver
from models import Comm_Queue
#receiver(pre_save, sender=Comm_Queue)
def get_sender_email_from_settings(sender, **kwargs):
obj=kwargs['instance']
if not obj.sender_email:
obj.sender_email='%s' % settings.ADMINS[0][1]
This code will not run because I import Comm_Queue inside signals.py and I also import the signals inside models.py.
Can anyone advice on how I could over come this issue?
Regards
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'
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.
Related discussion
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.
To solve your problem you just have to import signals.py after your model definition. That's all.
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.
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
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',
# ...
]
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.
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.
I have an application that works absolutely fine when run as ./manage.py runserver (or even runserver_plus), but when I deploy it to an apache2+wsgi instance, it breaks. The first model it tries to import (UserProfile) it appears to have imported the requested modules as NoneType.
So, a model like this (this is not exact code, it's not something I can paste onto a public site right now):
from django.db import models
from django.contrib.auth.models import User
from BlogEngine.categorisation.models import Category
from django.db.models.signals import post_save
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import ugettext as _
import logging
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
category = models.ManyToManyField(Category, blank=True, related_name="category")
def __unicode__(self):
return "Profile for %s" % user.username
def update_categories(self):
"""Updates the categories list"""
pull_more = self.category_selection_max - self.category.count()
if pull_more == 0:
return self.category_selection
logging.debug("Drawing %s categories" % draw)
categories = Category.objects.filter(
is_live=True
).order_by("?")[:pull_more]
## More code under here ##
Returns:
'NoneType' object has no attribute 'debug'
at the line logging.debug("Drawing %s categories" % draw)
Commenting that out results in getting
'NoneType' object has no attribute 'objects'
at the line below it instead, and so on. Everything's definitely being imported, and it works fine under the dev server.
My WSGI file is:
import sys
import site
import os
vepath = '/home/aquarion/newsite/django/virtualenv/lib/python2.6/site-packages'
#prev_sys_path = list(sys.path)
## add the site-packages of our virtualenv as a site dir
site.addsitedir(vepath)
## add the app's directory to the PYTHONPATH
sys.path.append('/home/aquarion/newsite/django/')
# import from down here to pull in possible virtualenv django install
from django.core.handlers.wsgi import WSGIHandler
os.environ['DJANGO_SETTINGS_MODULE'] = 'BlogEngine.settings'
application = WSGIHandler()
Any ideas?
Solved it.
Not sure if it's a bug in something, but it ended up being an issue with using django's user profile stuff and having Admin model information in the models.py file. Once I moved all that into its own admin.py file, everything worked.
Still not sure what causes it exactly, but that's the solution.
(Solution reached via http://osdir.com/ml/DjangoUsers/2009-07/msg00090.html and its reply)