docs: def _users_watching_by_filter(self, object_id=None, exclude=None,
                                    **filters):
          """Return an iterable of (``User``/:class:`~tidings.models.EmailUser`,
          [:class:`~tidings.models.Watch` objects]) tuples watching the event.
  
          Of multiple Users/EmailUsers having the same email address, only one is
          returned. Users are favored over EmailUsers so we are sure to be able
          to, for example, include a link to a user profile in the mail.
  
          The list of :class:`~tidings.models.Watch` objects includes both
          those tied to the given User (if there is a registered user)
          and to any anonymous Watch having the same email address. This
          allows you to include all relevant unsubscribe URLs in a mail,
          for example. It also lets you make decisions in the
          :meth:`~tidings.events.EventUnion._mails()` method of
          :class:`~tidings.events.EventUnion` based on the kinds of
          watches found.
  
          "Watching the event" means having a Watch whose ``event_type`` is
          ``self.event_type``, whose ``content_type`` is ``self.content_type`` or
          ``NULL``, whose ``object_id`` is ``object_id`` or ``NULL``, and whose
          WatchFilter rows match as follows: each name/value pair given in
          ``filters`` must be matched by a related WatchFilter, or there must be
          no related WatchFilter having that name. If you find yourself wanting
          the lack of a particularly named WatchFilter to scuttle the match, use
          a different event_type instead.
  
          :arg exclude: If a saved user is passed in as this argument, that user
              will never be returned, though anonymous watches having the same
              email address may. A sequence of users may also be passed in.
  
          """
          # I don't think we can use the ORM here, as there's no way to get a
          # second condition (name=whatever) into a left join. However, if we
          # were willing to have 2 subqueries run for every watch row--select
          # {are there any filters with name=x?} and select {is there a filter
          # with name=x and value=y?}--we could do it with extra(). Then we could
          # have EventUnion simply | the QuerySets together, which would avoid
          # having to merge in Python.
  
          if exclude is None:
              exclude = []
          elif not isinstance(exclude, Sequence):
              exclude = [exclude]
  
          def filter_conditions():
              """Return joins, WHERE conditions, and params to bind to them in
              order to check a notification against all the given filters."""
              # Not a one-liner. You're welcome. :-)
              self._validate_filters(filters)
              joins, wheres, join_params, where_params = [], [], [], []
              for n, (k, v) in enumerate(iteritems(filters)):
                  joins.append(
                      'LEFT JOIN tidings_watchfilter f{n} '
                      'ON f{n}.watch_id=w.id '
                      'AND f{n}.name=%s'.format(n=n))
                  join_params.append(k)
                  wheres.append('(f{n}.value=%s '
                                'OR f{n}.value IS NULL)'.format(n=n))
                  where_params.append(hash_to_unsigned(v))
              return joins, wheres, join_params + where_params
  
          # Apply watchfilter constraints:
          joins, wheres, params = filter_conditions()
  
          # Start off with event_type, which is always a constraint. These go in
          # the `wheres` list to guarantee that the AND after the {wheres}
          # substitution in the query is okay.
          wheres.append('w.event_type=%s')
          params.append(self.event_type)
  
          # Constrain on other 1-to-1 attributes:
          if self.content_type:
              wheres.append('(w.content_type_id IS NULL '
                            'OR w.content_type_id=%s)')
              params.append(ContentType.objects.get_for_model(
                            self.content_type).id)
          if object_id:
              wheres.append('(w.object_id IS NULL OR w.object_id=%s)')
              params.append(object_id)
          if exclude:
              # Don't try excluding unsaved Users:1
              if not all(e.id for e in exclude):
                  raise ValueError("Can't exclude an unsaved User.")
  
              wheres.append('(u.id IS NULL OR u.id NOT IN (%s))' %
                            ', '.join('%s' for e in exclude))
              params.extend(e.id for e in exclude)
  
          def get_fields(model):
              if hasattr(model._meta, '_fields'):
                  # For django versions < 1.6
                  return model._meta._fields()
              else:
                  # For django versions >= 1.6
                  return model._meta.fields
  
          User = get_user_model()
          model_to_fields = dict((m, [f.get_attname() for f in get_fields(m)])
                                 for m in [User, Watch])
          query_fields = [
              'u.{0}'.format(field) for field in model_to_fields[User]]
          query_fields.extend([
              'w.{0}'.format(field) for field in model_to_fields[Watch]])
  
          query = (
              'SELECT {fields} '
              'FROM tidings_watch w '
              'LEFT JOIN {user_table} u ON u.id=w.user_id {joins} '
              'WHERE {wheres} '
              'AND (length(w.email)>0 OR length(u.email)>0) '
              'AND w.is_active '
              'ORDER BY u.email DESC, w.email DESC').format(
              fields=', '.join(query_fields),
              joins=' '.join(joins),
              wheres=' AND '.join(wheres),
              user_table=User._meta.db_table)
          # IIRC, the DESC ordering was something to do with the placement of
          # NULLs. Track this down and explain it.
  
          # Put watch in a list just for consistency. Once the pairs go through
          # _unique_by_email, watches will be in a list, and EventUnion uses the
          # same function to union already-list-enclosed pairs from individual
          # events.
          return _unique_by_email((u, [w]) for u, w in
                                  multi_raw(query, params, [User, Watch],
                                            model_to_fields))