Where to put signals?

519 views
Skip to first unread message

Benjamin Buch

unread,
Sep 28, 2008, 7:58:39 AM9/28/08
to Django users
Hi, 

I'm using the new comments framework, and I'd like to get notified by mail when someone posts a comment.
How to di it I think I know, but I'm not quite sure where the code should live.
The website has several kinds of entries where users can comment on, so it would feel a little odd to put the comments' signal-code in just one models.py.
As I have even more signals, I thought it would be great to have a file signals.py, where all signal handling is done.

But where should signals.py live?
Documentation says to signals:
"Where should this code live?
You can put signal handling and registration code anywhere you like. However, you'll need to make sure that the module it's in gets imported early on so that the signal handling gets registered before any signals need to be sent. This makes your app's models.py a good place to put registration of signal handlers."
What means "the module it's in gets imported early"?
I suppose it's not enough to put my signals.py right there in my projects' root folder?
-benjamin

Erik Allik

unread,
Sep 28, 2008, 11:14:30 AM9/28/08
to django...@googlegroups.com
The way I see it is that your comment notification is not tied to any particular application that has commentable models but instead is more like a project related thing. So depending on your source layout, I'd put them somewhere in the project. Basically this relates to the application reuse topic -- when you connect the handler to the comment signal, is it something you want to reuse in the future or it's just a one time thing for the current project?

Erik

Benjamin Buch

unread,
Sep 28, 2008, 12:03:52 PM9/28/08
to django...@googlegroups.com
Hi Erik,

thanks for your reply.
You are right, the comments are not tied to a particular model, but to three of them.
Instead of wiring up all three models, I thought I could do this in one place.
As I write this reply, I realize that it is perhaps not such a good idea to do so.
It would be good to have some information in the mail that says on exactly which model instance the comment was made on,
so it will be better to  wire up each model.

Thanks again anyway,
benjamin

Erik Allik

unread,
Sep 28, 2008, 12:27:26 PM9/28/08
to django...@googlegroups.com
But you only have a single comment model to wire to, unless I'm missing something.

Erik

Benjamin Buch

unread,
Sep 29, 2008, 8:36:55 AM9/29/08
to django...@googlegroups.com
No, I think you've got it right.
I should write the code first, and then say something about it I guess... ;-)
I'll get back when I did so.

Thanks for your reply,
benjamin

Benjamin Buch

unread,
Oct 29, 2008, 4:17:23 AM10/29/08
to django...@googlegroups.com
Hi,

short summary for all who didn't follow or don't remember (it's been a while since the last reply...):

I have signals wired up for comments (email-notification on commenting).
Users are allowed to comment on three different models.
Where should the code live?

Am 29.09.2008 um 14:36 schrieb Benjamin Buch:

I should write the code first, and then say something about it I guess... ;-)
I'll get back when I did so.
benjamin

I wrote the code now.
Here it is:

from django.contrib.comments.models import Comment
from django.core.mail import mail_managers
from django.contrib.comments.signals import comment_was_posted

def mail_on_posted_comment(sender, comment, request, **kwargs):
    name = comment.user_name
    email = comment_user_email
    comment_body = comment.comment
    ct = comment.content_type
    ct_name = ct.name
    ct_object = ct.get_object_for_this_type(pk=comment.object_pk)
    domain = comment.site.domain
    url_read = domain + ct_object.get_absolute_url()
    url_edit = domain + '/admin/comments/comment/' + str(comment.id)

    email_body = '''Ein neuer Kommentar wurde erstellt:
von: %s
E-mail: %s
zu: %s %s
Kommentar: %s

Kommentar lesen: %s
Kommentar bearbeiten: %s''' % (name, email, ct_name, ct_object, comment_body, url_read, url_edit)
    email_subject = 'Neuer Kommentar'
    mail_managers(email_subject, email_body)

comment_was_posted.connect(mail_on_posted_comment, sender=Comment)

So the question is: Where should this code live?

As Erik said, it's more of a project related thing (because you can comment on three different models),
so I think it would be a bad idea to tie the code to one particular model and put it in some models.py.

Other places I could think of but considered them as 'not so good':
__init__.py: Who would think that there are signals here? I guess nobody.
views.py: signals in views? I don't think so. Let's keep things separated.
urls.py: urls.py is for wiring up urls, not signals.

@Erik:
What exactly do you mean by 'put them somewhere in the project'?

benjamin

Adi Jörg Sieker

unread,
Oct 29, 2008, 7:09:19 AM10/29/08
to django...@googlegroups.com
Since a django application is a normal python module you
could create a signals.py and import it in your applications __init__.py
or whatever pleases you.
a django application can contain whatever new files modules you want.
It has to respect somethings so that django recognises it as an application
but other than that you are free to create whatever you want.

Gruß
adi
--
Adi J. Sieker mobile: +49 - 178 - 88 5 88 13
Freelance developer web: http://www.sieker.info/profile
SAP-Developer

Benjamin Buch

unread,
Oct 29, 2008, 7:49:08 AM10/29/08
to django...@googlegroups.com
The thing is, I don't want to tie the comments signals to a specific
application.
It's more of a project-wide thing.

So I did put the code into signals.py, stuffed it into my project root
(not in an app)
and imported it in my project's __init__.py.

Now I get this Error if I try to ./manage.py runserver:

Traceback (most recent call last):
File "./manage.py", line 11, in <module>
execute_manager(settings)
File "/Library/Python/2.5/site-packages/django/core/management/
__init__.py", line 338, in execute_manager
setup_environ(settings_mod)
File "/Library/Python/2.5/site-packages/django/core/management/
__init__.py", line 316, in setup_environ
project_module = __import__(project_name, {}, {}, [''])
File "/Users/benjamin/Code/django/kassette/../kassette/
__init__.py", line 1, in <module>
import signals.py
File "/Users/benjamin/Code/django/kassette/../kassette/signals.py",
line 1, in <module>
from django.contrib.comments.models import Comment
File "/Library/Python/2.5/site-packages/django/contrib/comments/
models.py", line 2, in <module>
from django.contrib.auth.models import User
File "/Library/Python/2.5/site-packages/django/contrib/auth/
models.py", line 6, in <module>
from django.db import models
File "/Library/Python/2.5/site-packages/django/db/__init__.py",
line 9, in <module>
if not settings.DATABASE_ENGINE:
File "/Library/Python/2.5/site-packages/django/conf/__init__.py",
line 28, in __getattr__
self._import_settings()
File "/Library/Python/2.5/site-packages/django/conf/__init__.py",
line 57, in _import_settings
raise ImportError("Settings cannot be imported, because
environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
ImportError: Settings cannot be imported, because environment variable
DJANGO_SETTINGS_MODULE is undefined.

Why do I have to set an environment variable for this?
Django never complained about this before.

@adi:
What do you mean by 'whatever pleases you'?

I understand that I can create any arbitrary .py-file with code that I
want and than import this file,
but I'm not quite sure from which file I should import it.
As seen above, importing from __init__.py results in quite some trouble.
But thanks for the reply!

benjamin

urukay

unread,
Oct 29, 2008, 8:07:25 AM10/29/08
to django...@googlegroups.com

Benjamin, i did't have to use singnals so far, but when something is needed
in various app (models), i create new app and put it there (e.g.
signals.py).
And you don't have to bother with cross imports exceptions, can change
everything in one place for each model etc.


Radovan
--
View this message in context: http://www.nabble.com/Where-to-put-signals--tp19710995p20225683.html
Sent from the django-users mailing list archive at Nabble.com.

Adi Jörg Sieker

unread,
Oct 29, 2008, 12:04:49 PM10/29/08
to django...@googlegroups.com
you can't put it in the projects __init__.py since that is imported
before django can initialize itself.

I sometimes just create a module named core in the project directory and
place stuf I need in various place there.
how about creating an app called global put the signals.py in there and
in the __init__.py do an import signals.

> @adi:
> What do you mean by 'whatever pleases you'?
>

naja, es ist egal wohin du die signals tust so lange es für dich passt
und es im Rahmen
der Django Vorgaben bleibt.

adi

Benjamin Buch

unread,
Oct 29, 2008, 12:14:27 PM10/29/08
to django...@googlegroups.com
Hi Radovan,

thanks for your reply!

Am 29.10.2008 um 13:07 schrieb urukay:

> Benjamin, i did't have to use singnals so far, but when something is
> needed
> in various app (models), i create new app and put it there (e.g.
> signals.py).
> And you don't have to bother with cross imports exceptions, can change
> everything in one place for each model etc.
>
>
> Radovan


I started a new app (./manage.py startapp) named 'utilities'
and put signals.py in it like this:

-project
-__init__.py
-settings.py
-urls.py
-utilities
-__init__.py
-signals.py

Then I added 'project.utilities' to INSTALLED_APPS in settings.py.

This way it did not work yet, I had to do what Adi proposed in an
earlier reply:
I had to import signals.py in the app's __init__.py.

benjamin


Benjamin Buch

unread,
Oct 29, 2008, 12:17:17 PM10/29/08
to django...@googlegroups.com
Hi Adi,

Radov proposed the same, I just answered to his reply...
It works like you two guys said!

Danke!

benjamin

Reply all
Reply to author
Forward
0 new messages