Getting information from Django custom signal receiver - django

This is my second question today actually but what I want to know...Is it possible to retrieve information from a signal handler.
I have a list of items, call it list and each item is in AppA. Each item has a couple of characteristics which are saved in a different app, AppB.
So, I figured that I could maybe create a dictionary, dict and iterate over the items in list. In each iteration, I was hoping to send a signal to AppB and retrieve the information, i.e. have something like
def blob(request):
dict = {}
for item in list:
signal.send(sender=None, id=item.id)
dict[item] = (char1, char2)
...some html request
My signal handler looks something like this:
def handler(sender, id, **kwargs):
model2 = Model2.objects.get(id=id)
a = model2.char1
b = model2.char2
return (a, b)
Then I was hoping to be able to just produce a list of the items and their characteristics in the webpage...THe problem is that obviously the signal sender has to send the signal, and get the information back which I want....is that even possible :S?
Currently, I get an error saying "global name 'char1' is not defined....and I have imported the handlers and signals into the view.py where blob resides....so is my problem just unsolvable? / Should it clearly be solved in another way? Or have I almost certainly made a stupid error with importing stuff?

This wasn't actually so tricky. Thought I should perhaps post how it was solved. In my views, I actually wrote
response_list=signal.send(sender=None, list=list_of_items)
I then iterated over my response_list, adding the items to a fresh list like so:
snippets = []
for response in response_list:
logger.error(response)
snippets.append(response[1])
And could then call the responses in snippets like a dictionary in my template. When I asked the question, I didn't appreciate that I could equate something with the signal sending...

Related

How to call a function from views.py to tasks.py?

I'm trying this: but its throwing an TypeError: auto_sms() missing 1 required positional argument: 'request' error.
Now I'm thinking of getting the function from views.py instead and calling it on tasks.py if requests is not working on tasks.py, how can I do it? Thanks!
#shared_task
def auto_sms(request):
responses = Rainfall.objects.filter(
level='Torrential' or 'Intense',
timestamp__gt=now() - timedelta(days=1),
)
count = responses.count()
if not (count % 10) and count > 0:
send_sms(request)
return
Passing the entire request is probably not a good idea since it can include Django model objects such as a user object. Now the problem that you will face is that if there is an object that is not serializable, then you'll get an error while calling the function. So instead of passing the whole request, just send the data that you actually need.
For example, I'm guessing you need the user here to send an SMS to. So instead of passing the whole request with the user object included, then just send the user_id and then get the user there. basically, you have to make sure that the data you're passing is serializable.
It's generally a good idea to pass ids of the Django models since the data might change while your function is being processed and you might get the old data if you pass the whole data.

Custom Django signal receiver getting data

I'm very new to programming and especially to Django but can't work out how to use any previous answers to my advantage....
Apologies if my question is too vague but essentially, I have two different apps, let's call them app A and app B, with data on two different databases but apps contain information on the same individual item.
I want to edit this information on my 'edit details' page while keeping the apps as separate as possible (well AppB can know about functions in AppA but not vice-versa)...I guess what I really want is a signal which works like so:
A 'submit' view within AppA which is called when I submit changes to the data (using text boxes). The data for AppA is then saved..
And a signal then sent to AppB which ideally would update its data, before the HttpResponseRedirect is performed.
Unfortunately I can't really get this to work. My problem is that if I put 'request' into the arguments for save_details, I get errors like "save_details() takes exactly 3 arguments (2 given)"....does anyone know a clever way of getting something like this to work?
My submit function in AppA looks something like this...
def submit(self, request, id):
signal_received.send(sender=self, id=id)
q = get_object_or_404(AppA, pk=id)
q.blah = request.POST.get('wibble from the form')
...
return Http.....
in my AppB signals.py file, I have put.
signal_received = django.dispatch.Signal(providing_args=['id'])
def save_details(sender, uid, **kwargs):
p = AppB.objects.get(id=id)
p.wobble = request.POST.get('wobble from the form')
...
signal.received.connect(save_details)
Obviously the above doesn't mention request in its arguments which seems to be necessary but if I add that, I get problems with the number of arguments.
(I have imported all the right things at the top of each file I think...hence me leaving that off.)
Any point about the above would be appreciated....e.g. does "request" need to be the first argument? It didn't seem to like me using "self" before but I have tried to copy as much as possible the example at the bottom of the documentation (https://docs.djangoproject.com/en/dev/topics/signals/) but the extra functionality I need in the signal receiving function is flumoxing me.
Thanks in advance...

Implementing unread/read checking for a message

I'm having a message model. To this model I want to add a read/unread field, which I did by using a boolean field. Now, if someone reads this message, I want this boolean field to be turned to true. I access these messages at different parts in my app, so updating the field manually is going to be tedious.
Is there any way I can get some messages according to some condition, and when the message is fetched from db, the field gets auto updated?
Why don't you create a read_message() method on a custom model manager. Have this method return the messages you want, whilst also updating the field on each message returned.
You new method allow you to replace Message.objects.get() with Message.objects.read_message()
class MessageManager(models.Manager):
def read_message(self, message_id):
# This won't fail quietly it'll raise an ObjectDoesNotExist exception
message = super(MessageManager, self).get(pk=message_id)
message.read = True
message.save()
return message
Then include the manager on your model -
class Message(models.Model):
objects = MessageManager()
Obviously you could write other methods that return querysets whilst marking all the messages returned as read.
If you don't want to update your code (places where you call Message.objects.get()), then you could always actually override get() so that it updates the read field. Just replace the read_message function name above with get.
Depending on your database management system, you may be able to install a trigger:
PostgreSQL: http://www.postgresql.org/docs/9.1/static/sql-createtrigger.html
MySQL: http://dev.mysql.com/doc/refman/5.0/en/triggers.html
SQLite: http://www.sqlite.org/lang_createtrigger.html
Of course, this will need to be done manually in the database - outside of the Django application.

Django, Tastypie and retrieving the new object data

Im playing a little bit with heavy-client app.
Imagine I have this model:
class Category(models.Model):
name = models.CharField(max_length=30)
color = models.CharField(max_length=9)
Im using knockoutjs (but I guess this is not important). I have a list (observableArray) with categories and I want to create a new category.
I create a new object and I push it to the list. So far so good.
What about saving it on my db? Because I'm using tastypie I can make a POST to '/api/v1/category/' and voilĂ , the new category is on the DB.
Ok, but... I haven't refresh the page, so... if I want to update the new category, how I do it?
I mean, when I retrieve the categories, I can save the ID so I can make a put to '/api/v1/category/id' and save the changes, but... when I create a new category, the DB assign a id to it, but my javascript doesn't know that id yet.
in other words, the workflow is something like:
make a get > push the existing objects (with their ids) on a list > create a new category > push it on the list > save the existing category (the category doesnt have the id on the javacript) > edit the category > How I save the changes?
So, my question is, what's the common path? I thought about sending the category and retrieving the id somehow and assign it to my object on js to be able to modify it later. The problem is that making a POST to the server doesn't return anything.
In the past I did something like that, send the object via post, save it, retrieve it and send it back, on the success method retrieve the id and assign it to the js object.
Thanks!
Tastypie comes with an always_return_data option for Resources.
When always_return_data=True for your Resource, the API always returns the full object event on POST/PUT, so that when you create a new object you can get the created ID on the same request.
You can then just read the response from your AJAX and decode the JSON (i dont know about knockout yet).
see the doc : http://readthedocs.org/docs/django-tastypie/en/latest/resources.html?highlight=always_return_data#always-return-data
Hope this helps

How do I build a queryset in django retrieving threads in which a user has posted?

I'm making a threaded forum app using django-mptt. Everything is up and running, but I have trouble building one specific queryset.
I want to retrieve posts which:
are root nodes
are posted by current_user or have a descendant posted by current_user.
What I have so far is this:
Post.objects.filter(Q(user = current_user) | Q( )).exclude(parent__gt = 0)
in my second Q I need something to tell whether the current_user has posted one of its descendants. Anyone know if it's even possible?
I don't think you can do this in one query. Here's how to do it in two:
thread_ids = Post.objects.filter(user=current_user).values_list('tree_id', flat=True)
posts = Post.objects.filter(tree_id__in=thread_ids, level=0)
This gets the MPTT tree id of every thread which the user has posted in. Then it gets the root node of each of these threads.