def handle(self, msg): match = self.FOLLOW_RE.match(msg.text) if match is not None: # fetch a list of objects (any model) that # match the query via the __search__ api to_follow = find_objects( followable_models(), match.group(1)) # link this reporter to the "followers" reverse foreign key # of each object (whatever model it is -- they're all named # "followers"). this works with unidentified connections too, # even if that doesn't make much sense most of the time for obj in to_follow: obj.followers.get_or_create(**msg.persistance_dict) if to_follow: msg.respond( u"You are now following: %s" % (", ".join(map(unicode, to_follow)))) # if we didn't understand _any_ of what the # caller asked us to follow, return an error else: msg.respond(u"Sorry, I couldn't understand what you want to follow") return True # is this an unfollow request? pass # is this a "who am i following?" request? pass
#!/usr/bin/env python # vim: ai ts=4 sts=4 et sw=4 from django.db import models from reporters.models import Reporter, PersistantConnection from utils import followable_models for model in followable_models(): m_name = "Following%s" % model.__name__ # believe it or not, this is how django generates the field names for # many-to-one (reverse foreign key) relationships. so i'm doing the same. # see: django.db.models.fields.related.RelatedField.contribute_to_class f_name = "following_%s" % model.__name__.lower() r_name = "%s_set" % f_name # dynamically build a django model in this scope, and link # it back to the target via the __follow_model__ attribute, # so it can be found later on via the original model vars()[m_name] = model.__follow_model__ = type(m_name, (models.Model,), { f_name: models.ForeignKey(model, related_name="followers"), # allow reporters OR connections to follow other objects. this doesn't # make much sense, but is allowed for the sake of completeness. it can # always be disallowed in app.py "reporter": models.ForeignKey(Reporter, null=True, related_name=r_name), "connection": models.ForeignKey(PersistantConnection, null=True, related_name=r_name), # replace the verbose name, to shorten the