Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs #13

Merged
merged 34 commits into from
Dec 29, 2014
Merged

Docs #13

Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d4c5983
Docs for events methods on Medium objects
swans-one Dec 17, 2014
80473da
Docs for utility functions.
swans-one Dec 17, 2014
fe988bf
followers_of and followed_by docs
swans-one Dec 17, 2014
6c6f145
create_events docs
swans-one Dec 17, 2014
e15d7a6
Return type-annotations and descriptions
swans-one Dec 17, 2014
bf9bddb
Source and Medium documentation.
swans-one Dec 17, 2014
6b18a75
SourceGroup and Unsubscription docs
swans-one Dec 17, 2014
4aa1366
Subscription docs
swans-one Dec 17, 2014
98dc2e7
Event documentation
swans-one Dec 17, 2014
4b6385d
EventActor, EventSeen docs
swans-one Dec 17, 2014
60828af
remove mark-seen todo
swans-one Dec 17, 2014
c2343b9
Merge develop
swans-one Dec 17, 2014
0b65fd4
spelling corrections
swans-one Dec 17, 2014
f784e65
Sphinx Basic Setup and autodoc
swans-one Dec 17, 2014
342037f
Import models in __init__.py
swans-one Dec 18, 2014
4acb536
Creating and Categorizing events docs
swans-one Dec 18, 2014
1dcdb87
Medium and Subscription creation docs
swans-one Dec 18, 2014
d56ccd0
Querying events docs.
swans-one Dec 18, 2014
0502576
spelling fixes
swans-one Dec 18, 2014
4525555
Code block syntax fix
swans-one Dec 18, 2014
a67f571
Minor version number bump.
swans-one Dec 18, 2014
a37b794
Advanced Features docs.
swans-one Dec 18, 2014
f1dd28e
Release notes for v0.2
swans-one Dec 18, 2014
8e444fe
Added cross referencing links
swans-one Dec 18, 2014
3553fcd
Add actors argument documentation.
swans-one Dec 18, 2014
cfeaf8c
Update readme
swans-one Dec 18, 2014
54c7862
small corrections
swans-one Dec 19, 2014
0e75e81
Quickstart corrections.
swans-one Dec 19, 2014
89cda82
Medium typo
swans-one Dec 19, 2014
314e191
Better documentation of create_event args
swans-one Dec 19, 2014
6997882
Param docs for followers_of, followed_by
swans-one Dec 19, 2014
6608c5f
Entity or EntityQuerySet clarification
swans-one Dec 19, 2014
bbcd892
Fixed double parameters and method signatures
swans-one Dec 19, 2014
deaa8c7
Clarify behavior of followers_of and followed_by
swans-one Dec 19, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@
:alt: Number of PyPI downloads


django-entity-event
===============

Newsfeed-style event tracking and subscription management for django-entity.
Django Entity Event
===================

Django Entity Event is a great way to collect events that your users
care about into a unified location. The parts of your code base that
create these events are probably totally separate from the parts that
display them, which are also separate from the parts that manage
subscriptions to notifications. Django Entity Event makes separating
these concerns as simple as possible, and provides convenient
abstractions at each of these levels.

Installation
------------
Expand Down
154 changes: 154 additions & 0 deletions docs/advanced_features.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
Advanced Features
=================

The :ref:`quickstart` guide covers the common use cases of Django Entity
Event. In addition to the basic uses for creating, storing, and
querying events, there are some more advanced uses supported for
making Django Entity Event more efficient and flexible.

This guide will cover the following advanced use cases:

- Dynamically loading context using ``context_loader``
- Customizing the behavior of ``only_following`` by sub-classing
:py:class:`~entity_event.models.Medium`.


Custom Context Loaders
----------------------

When events are created, it is up to the creator of the event to
decide what information gets stored in the event's ``context``
field. In many cases it makes sense to persist all of the data
necessary to display the event to a user.

In some cases, however the ``context`` of the event can be very large,
and storing all of the information would mean duplicating a large
amount of data that exists elsewhere in your database. It's desirable
to have all this data available in the ``context`` field, but it isn't
desirable to repeatedly duplicate large amounts of information.

If the creator of the events can guarantee that some of the
information about the event will always be available in the database,
or computable from some subset of the data that could be stored in the
context, they can use the ``Source.context_loader`` field to provide a
path to an importable function to dynamically load the context when
the events are fetched.

If for example, we are creating events about photo tags, and we don't
want to persist a full path to the photo, we can simply store a ``id``
for the photo, and then use a context loader to load it
dynamically. The function we would write to load the context would
look something like

.. code-block:: python

# In module apps.photos.loaders

def load_photo_context(context):
photo = Photo.objects.get(id=context['photo_id'])
context['photo_path'] = photo.path
return context

Then, when defining our source for this type of event we would include
a path to this function in the ``context_loader`` field.

.. code-block:: python

from entity_event import Source

photo_tag_source = Source.objects.create(
name="photo-tag",
display_name="Photo Tag",
description="You are tagged in a photo",
group=photo_group,
context_loader='apps.photos.loaders.load_photo_path'
)

With this setup, all of the additional information can by dynamically
loaded into events, simply by calling :py:meth:`Event.get_context
<entity_event.models.Event.get_context>`.

The ``Source`` model also uses django's ``clean`` method to ensure
that only valid importable functions get saved in the
database. However, if this function is removed from the codebase,
without a proper migration, attempting to load context for events with
this source will fail.

There are a number of trade-offs in using a context loader. If the
underlying data is subject to change, accessing historic events could
cause errors in the application. Additionally, a context loader that
requires many runs to the database could cause accessing events to be
a much more expensive operation. In either of these cases it makes
more sense to store copies of the data in the ``context`` field of the
event.


Customizing Only-Following Behavior
-----------------------------------

In the quickstart, we discussed the use of "only following"
subscriptions to ensure that users only see the events that they are
interested in. In this discussion, we mentioned that by default,
entities follow themselves, and their super entities. This following
relationship is defined in two methods on the
:py:class:`~entity_event.models.Medium` model:
:py:meth:`Medium.followers_of
<entity_event.models.Medium.followers_of>` and
:py:meth:`Medium.followed_by
<entity_event.models.Medium.followed_by>`. These two methods are
inverses of each other and are used by the code that fetches events to
determine the semantics of "only following" subscriptions.

It is possible to customize the behavior of these types of
subscriptions by concretely inheriting from
:py:class:`~entity_event.models.Medium`, and overriding these two
functions. For example, we could define a type of medium that provides
the opposite behavior, where entities follow themselves and their
sub-entities.

.. code-block:: python

from entity import Entity, EntityRelationship
from entity_event import Medium

class FollowSubEntitiesMedium(Medium):
def followers_of(self, entities):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be

def followers_of(self, entity)

both here and in the code base?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, both of these methods can take either a single entity, or a queryset of entities.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I clarified this a little further.

if isinstance(entities, Entity):
entities = Entity.objects.filter(id=entities.id)
super_entities = EntityRelationship.objects.filter(
sub_entity__in=entities).values_list('super_entity')
followed_by = Entity.objects.filter(
Q(id__in=entities) | Q(id__in=super_entities))
return followed_by

def followed_by(self, entities):
if isinstance(entities, Entity):
entities = Entity.objects.filter(id=entities.id)
sub_entities = EntityRelationship.objects.filter(
super_entity__in=entities).values_list('sub_entity')
followers_of = Entity.objects.filter(
Q(id__in=entities) | Q(id__in=sub_entities))
return followers_of

With these methods overridden, the behavior of the methods
``FollowsubEntitiesMedium.events``,
``FollowsubEntitiesMedium.entity_events``, and
``FollowsubEntitiesMedium.events_targets`` should all behave as
expected.

It is entirely possible to define more complex following
relationships, potentially drawing on different source of information
for what entities should follow what entities. The only important
consideration is that the ``followers_of`` method must be the inverse
of the ``followed_by`` method. That is, for any set of entities, it
must hold that

.. code-block:: python

followers_of(followed_by(entities)) == entities

and

.. code-block:: python

followed_by(followers_of(entities)) == entities
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def get_version():
source_suffix = '.rst'

# The master toctree document.
master_doc = 'toc'
master_doc = 'index'

# General information about the project.
project = u'entity_event'
Expand Down Expand Up @@ -189,4 +189,4 @@ def process_django_model_docstring(app, what, name, obj, options, lines):

def setup(app):
# Register the docstring processor with sphinx
app.connect('autodoc-process-docstring', process_django_model_docstring)
app.connect('autodoc-process-docstring', process_django_model_docstring)
25 changes: 22 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
django-entity-event Documentation
=================================
Django Entity Event
===================

Please put a description here, followed by sections for configuration, basic usage, and code documentation.
Django Entity Event is a framework for storing events, managing users
subscriptions to those events, and providing clean ways to make
notifying users as easy as possible. It builds on the `Django
Entity's`_ powerful method of unifying individuals and groups into a
consistent framework.

.. _Django Entity's: https://github.com/ambitioninc/django-entity/

Table of Contents
-----------------

.. toctree::
:maxdepth: 2

installation
quickstart
advanced_features
ref/entity_event
contributing
release_notes
25 changes: 22 additions & 3 deletions docs/installation.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
Installation
============

To install the latest release, type::
Django Entity Event is compatible with Python versions 2.7, 3.3, and
3.4.

Installation with Pip
---------------------

Entity Event is available on PyPi. It can be installed using ``pip``::

pip install django-entity-event

To install the latest code directly from source, type::
Use with Django
---------------

To use Entity Event with django, first be sure to install it and/or
include it in your ``requirements.txt`` Then include
``'entity_event'`` in ``settings.INSTALLED_APPS``. After it is
included in your installed apps, run::

./manage.py migrate entity_event

if you are using South_. Otherwise run::

./manage.py syncdb

.. _South: http://south.aeracode.org/

pip install git+git://github.com/ambitioninc/django-entity-event.git
Loading