{ "info": { "author": "Erik Swanson", "author_email": "opensource@ambition.com", "bugtrack_url": null, "classifiers": [ "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python" ], "description": "Django Entity Subscription\n==================================================\n\nDjango Entity Subscription uses the power of the `Django-Entity`_\nframework to make managing subscriptions easy and powerful, for you\nand your users.\n\n.. _`Django-Entity`: https://github.com/ambitioninc/django-entity\n\n\nOverview\n--------------------------------------------------\n\nThis django app, includes four models:\n\n- ``Subscription``\n- ``Unsubscribe``\n- ``Medium``\n- ``Source``\n\nall available from within the package ``entity_subscription.models``.\n\nBy creating objects in these models, you and the users of your\napplication can have fine grained control over how users are notified\nand about what they are notified. The ``entity_subscription`` app is\nagnostic about how users are actually notified about the subscriptions\nthat are set up, but is designed to be a dependency of whatever\nnotification system is put in place. It is assumed that the consumer\nof this library already has some idea of what notifications are going\nto be sent, and what delivery methods are going to be used to send the\nnotifications.\n\nOnce subscription information is stored in those models, the\n``entity_subscription`` app also provides some methods to make it\neasier to reason about and act on the stored subscriptions.\n\n- ``Subscription.objects.mediums_subscribed``\n- ``Subscription.objects.is_subscribed``\n\nSources and Mediums\n--------------------------------------------------\n\nThe ``entity_subscription`` app creates a strong boundary between the\n\"source\" of notifications from within an application and the \"medium\"\nused to deliver the notification to the users of the application.\n\n\nSources\n``````````````````````````````````````````````````\nFrom a user of your application's perspective a \"source\" is a category\nof notifications that they can subscribe to, or unsubscribe from. It\ncould be something like \"New Products\" or \"Important Site\nChanges\".\n\nFor any given source, users may want to receive notifications over\ndifferent mediums (like \"Email\", \"In-site\", \"text-message\"). By\ndividing notifications into different sources, users can choose to\nreceive that type of notification over whatever medium they prefer.\n\nTo achieve this within an application a \"source\" of notifications is\nan object that describes where in the app a notification came\nfrom. Pieces of code that originate events which lead to notifications\nwill want to own a ``Source`` object, or at least know the name of one,\nso that they can clearly communicate the ``source`` of the\nnotifications they are originating.\n\nThe actual source objects in the database are fairly simple, and are\ncreated through the standard ``objects.create`` interface. They have a\nunique identifier, a user friendly display name, and a longer form\ndescription.\n\n.. code:: Python\n\n from entity_subscription.models import Source\n\n Source.objects.create(\n name='new_products',\n display_name='New Products',\n description='Tells you whenever a new item is available in the store.'\n )\n\n\nMediums\n``````````````````````````````````````````````````\n\nFrom a user of your application's perspective a \"medium\" is a way in\nwhich they can be notified. Your site may support a variety of\ndifferent mediums for notifying your users of different\nhappenings. Examples could include Email, Text Messages, a News-Feed,\nor a In-site Notification center.\n\nUsers will likely want to receive notifications through some\ncombination of the available mediums, but only for certain categories\nof notifications. They may want some notifications that they view as\nsomewhat important to go to their email, notifications that are very\nimportant to go to email and text-message, and all the rest to go to\nan in-site notification center. By distinguishing between mediums in a\nsubscription library, users can decide how each \"source\" of\nnotifications is delivered to them.\n\nThe pieces of the application that handle actually sending\nnotifications will want to own a ``Medium`` object that describes\nthem, or at least know the unique name of one. This enables the code\nsending notifications to handle subscriptions appropriately.\n\nAs with sources, The actual medium objects in the database are fairly\nsimple, and are created through the standard ``objects.create``\ninterface. They have a unique identifier, a user friendly display\nname, and a longer form description.\n\n.. code:: Python\n\n from entity_subscription.models import Medium\n\n Medium.objects.create(\n name='in_site',\n display_name='In Site',\n description='Notifications available in the Accounts/Notifications tab.'\n )\n\n\nSource and Medium Considerations\n``````````````````````````````````````````````````\n\nBoth ``Source`` and ``Medium`` objects can be effectively used as\nstatic records that are setup as initial data for an application, or\nas dynamic records that change as the various sources and mediums for\nnotification change. It is important to consider, however, that\nexcessively dynamic sources and mediums will make it difficult for\nindividual entities to control their subscriptions.\n\n\nSubscriptions and Unsubscribing\n--------------------------------------------------\n\nEntities and groups of entities can be subscribed to\nnotifications. Once subscribed, individuals, mirrored as entities, can\nchoose to unsubscribe from notifications for a given source and\nmedium.\n\n\nSubscriptions\n``````````````````````````````````````````````````\n\nSubscriptions will most often be created by the application, for an\nentire group of entities. In this case, all the entities will receive\nthe notification, unless they later opt out. Subscriptions can also be\ncreated for an individual entity to receive a certain type of\nnotification, as an opt-in subscription.\n\nThis library includes the table ``Subscription``, available from\n``entity_subscription.models.Subscription``. Creating a\n``Subscription`` object is straightforward, assuming the relevant\n``Source`` and ``Medium`` objects have been created (See \"Sources and\nMediums\" above), and the entities to be subscribed and their group are\nappropriately mirrored. From there, we can use the standard\n``objects.create`` interface.\n\nGiven the sources and mediums created above, and a relationship\nbetween ``MyUser`` and ``MyGroup`` in a given application, the\nfollowing is a subscription for all the users in a particular group:\n\n.. code:: Python\n\n from my_app.models import MyUser\n from my_app.models import MyGroup\n\n from entity.models import Entity, EntityKind\n from entity_subscription.models import Subscription, Source, Medium\n\n super_entity = MyGroup.objects.get(name='product_group')\n Subscription.objects.create(\n medium = Medium.objects.get(name='in_site'),\n source = Source.objects.get(name='new_products'),\n entity = Entity.objects.get_for_obj(super_entity),\n subentity_kind = EntityKind.objects.get(name='myuser')\n )\n\nEach ``Subscription`` object stored in the database only subscribes\nthe group of entities to a single combination of a ``Source`` and\n``Medium``. To create subscriptions for delivering notifications from\nthe same source over different mediums, a new ``Subscription`` object\nmust be created for each source/medium combination. This allows the\napplication developer and the users to have detailed control over what\nthe users are notified about, and how those notifications are\ndelivered.\n\n\nUnsubscribing\n``````````````````````````````````````````````````\n\nIndividual users of your application may wish to remove themselves\nfrom receiving certain types of notifications.\n\nTo unsubscribe an individual from from receiving notifications of a\ngiven source/medium combination is as simple as creating an\n``Unsubscribe`` object. Assuming that \"Robert\" was subscribed to New\nProduct notifications in the subscription object above, unsubscribing\nhim from these notifications looks like:\n\n.. code:: Python\n\n from my_app.models import MyUser\n\n from entity.models import Entity\n from entity_subscription.models import Unsubscribe, Source, Medium\n\n Robert = MyUser.objects.get(name='Robert')\n\n Unsubscribe.objects.create(\n entity = Entity.objects.get_for_obj(Robert)\n medium = Medium.objects.get(name='in_site')\n sorce = Source.objects.get(name='new_products')\n )\n\nWith this object created, the rest of the group will receive these\nnotifications still, however \"Robert\" will no longer see them.\n\nSubscriptions and Unsubscribing Considerations\n``````````````````````````````````````````````````\n\nSeparating subscriptions and unsubscriptions into separate tables\nallows for groups of entities to be subscribed with a single object in\nthe ``Subscription`` table. This is useful for subscribing large\ngroups of users to a notification by default.\n\nIf a given notification may only have a few users interested in\nreceiving, it may make more sense for it to be an opt-in notification,\nwhere a Subscription object is made for each single entity that wishes\nto opt in (that is, a ``Subscription`` object with a\n``subentity_kind=None``). This may make more sense then subscribing\nlarge groups to this notification and having most of them unsubscribe.\n\n\nChecking Subscriptions\n--------------------------------------------------\n\nOnce your sites subscriptions are stored as shown above, you will want\nto use those subscriptions to decide to deliver (or not deliver)\nnotifications. The ``entity_subscription`` app provides a couple\nmethods to make it easier to find who is subscribed to what.\n\nThe ``SubscriptionManager``\n The following methods are available from the manager of the\n ``Subscription`` model.\n\n ``mediums_subscribed(source, entity, subentity_kind=None)``\n Return a queryset of all the mediums the given ``entity`` is\n subscribed to, for the given ``source``.\n\n If the optional ``subentity_kind`` parameter is given, return\n *every* medium that any of the given ``entity``'s sub-entities, of\n the given ``EntityKind``, is subscribed to.\n\n ``is_subscribed(source, medium, entity, subentity_kind=None)``\n Return a Boolean, indicating if the entity is subscribed to the\n given ``source`` on the given ``medium``.\n\n If the optional ``subentity_kind`` parameter is not ``None``,\n return ``True`` if *any* of the ``entity``'s sub-entities, of the\n given type, are subscribed to the given ``source`` on the given\n ``medium``.\n\nIn the common case, checking for subscriptions involves looking at the\nmediums a single entity is subscribed to. In this case both\n``mediums_subscribed`` and ``is_subscribed`` should behave exactly as\nexpected. Their exact behavior is described in more detail below, in\nthe section \"Checking if an individual entity is subscribed\".\n\nThe implications of including a ``subentity_kind`` argument are\nsomewhat more subtle. These implications are described in more detail\nbelow, in the section \"Checking if anyone in a group is subscribed\".\n\n\nChecking if an individual entity is subscribed\n``````````````````````````````````````````````````\n\nBefore sending notifications to users, your application wants to make\nsure that it's sending those notifications to users who have been\nincluded through a subscription, and not excluded themselves by\nunsubscribing.\n\nTo check the subscription status of a single entity, simply call\n``mediums_subscribed`` if you want a list of all the mediums an entity\nis subscribed to, for a given source, or call ``is_subscribed`` if you\nwant to check if that entity is subscribed to a particular medium for\na given source. When checking the subscription status of a single\nentity, the ``subentity_kind`` argument should be left as ``None``.\n\nWhen ``mediums_subscribed`` or ``is_subscribed`` are called without a\n``subentity_kind`` argument, the behavior of these methods is\nstraightforward. They will return a medium, or return true for that\nmedium, only if:\n\n1. The entity is part of a individual subscription, or is part of a\ngroup subscription for the given source.\n\n2. The entity is not unsubscribed from that source and medium.\n\nOnce you have checked that an individual entity is subscribed to a\ngiven source/medium combination, you can be confident in delivering\nthat notification.\n\n\nChecking if anyone in a group is subscribed\n``````````````````````````````````````````````````\n\nIn some cases, your application may have an event that applies to a\ngroup of individuals, and you may wish to check if any of those\nindividuals are subscribed to receive notifications for that\nevent.\n\nBoth ``mediums_subscribed`` and ``is_subscribed`` can also take an\noptional parameter ``subentity_kind`` which will change their\nbehavior fairly significantly. In this case, the provided argument,\n``entity``, is assumed to be a super-entity, and these functions\nreturn values based on what *any* of the sub entities are subscribed\nto.\n\nSo, passing in a super-entity, and subentity-type to either\n``mediums_subscribed`` or ``is_subscribed`` can provide a useful start\nfor delivering notifications.\n\nNote that this is only an *approximation* of what individuals in the\ngroup are subscribed to. Before actually delivering a notification\nto any subentity, the application must check that each user is\nactually subscribed to receive that notification.\n\n\nFiltering entities based on subscriptions\n``````````````````````````````````````````````````\n\nGiven some number of entities, that may or may not be subscribed to\nnotifications from a given source and medium, it could be complicated\nto determine all the possible entity relationships, and the relevant\nsubscriptions and unsubscriptions to check exactly which of those\nentities should be notified. The entity-subscription framework\nprovides a method, ``Subscription.objects.filter_not_subscribed`` that\nwill take the list of entities and return only those that should\ndefinitely recieve the notification.\n\n.. code:: Python\n\n entities = [entity_1, entity_2, entity_3]\n subscribed_entities = Subscription.objects.filter_not_subscribed(source, medium, entities)\n\nThis method returns a queryset of entities to be notified. It takes\ninto account all possible group subscriptions the entities may belong\nto, as well as removing entities that are unsubscribed from these\nnotifications.\n\nIt does, require, however, that all the entities provided are of the\nsame ``entity_kind``.\n\n\nRelease notes\n``````````````````````````````````````````````````\n\n* 0.4.0\n\n * Migrated Django Entity Subscription to use the ``EntityKind`` model for specifying\n different kinds of entities. This was a new addition in Django Entity 1.5. Schema migrations\n are provided that remove the ``subentity_type`` ``ContentType`` variable from the ``Subscription``\n model and add the ``subentity_kind`` ``EntityKind`` variable. Note that it is up to the\n user to write the appropriate data migration for converting entity types to entity kinds.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ambitioninc/django-entity-subscription", "keywords": "", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "django-entity-subscription", "package_url": "https://pypi.org/project/django-entity-subscription/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-entity-subscription/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/ambitioninc/django-entity-subscription" }, "release_url": "https://pypi.org/project/django-entity-subscription/0.4.1/", "requires_dist": null, "requires_python": null, "summary": "Make subscription management easy and entity-based.", "version": "0.4.1" }, "last_serial": 1242637, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "b1a4c7fbb452e51b02d50bc072549107", "sha256": "f1631d908a96d0d63ce02591b5694a389154c9f69f18ed90fe55c62133403ae9" }, "downloads": -1, "filename": "django-entity-subscription-0.1.tar.gz", "has_sig": false, "md5_digest": "b1a4c7fbb452e51b02d50bc072549107", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14780, "upload_time": "2014-06-12T17:42:51", "url": "https://files.pythonhosted.org/packages/ea/8f/29b2764d591b2113fbf795d008082910c745efd485a0336bee76373bac97/django-entity-subscription-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "8913e4e21d9e4bf8cb5642f8ceff55b0", "sha256": "cf60e15968fbca6c33c196a121cafdf8d56cb090e4e673547cae81a54c0a24fc" }, "downloads": -1, "filename": "django-entity-subscription-0.1.1.tar.gz", "has_sig": false, "md5_digest": "8913e4e21d9e4bf8cb5642f8ceff55b0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15695, "upload_time": "2014-06-18T15:29:09", "url": "https://files.pythonhosted.org/packages/07/51/980d83f8611725fcd4e7b2849e37e2fac4fcc9ef83ed42b76bcd7722ad49/django-entity-subscription-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "0dd9493a773e752793445512fc6ceb68", "sha256": "4926664943a2e1bbbddbeac2326cac943c2d4e008635c0845e59288c085258ff" }, "downloads": -1, "filename": "django-entity-subscription-0.1.2.tar.gz", "has_sig": false, "md5_digest": "0dd9493a773e752793445512fc6ceb68", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15742, "upload_time": "2014-06-24T15:14:13", "url": "https://files.pythonhosted.org/packages/1f/ca/57792f270015716b203b50f15d70922e3e722954463a413f06ba23de1d3a/django-entity-subscription-0.1.2.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "e979c779d92b3f18e1a253e799c3eefb", "sha256": "5eea273623b30fbf360d50f7f557a9ee8d608aa7e7eb4e4509cca8404ba87e43" }, "downloads": -1, "filename": "django-entity-subscription-0.2.0.tar.gz", "has_sig": false, "md5_digest": "e979c779d92b3f18e1a253e799c3eefb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17052, "upload_time": "2014-07-03T14:14:57", "url": "https://files.pythonhosted.org/packages/ab/d9/ced1a0639fe546d851fb8936c2d276b4c13170200774317f0d1abcbd8191/django-entity-subscription-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "9332a45d06a67488b77c6ff7f0b1a25a", "sha256": "f18baa91f38d31235a5f93ec06bed2d5b51cd15cd5eab00311cd8089528d20bd" }, "downloads": -1, "filename": "django-entity-subscription-0.2.1.tar.gz", "has_sig": false, "md5_digest": "9332a45d06a67488b77c6ff7f0b1a25a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17147, "upload_time": "2014-07-09T19:47:23", "url": "https://files.pythonhosted.org/packages/69/c4/0f4cdfcc640d676b3e13f0cb58d428af8ea485921fcc773786be375c1c95/django-entity-subscription-0.2.1.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "6207f104a7f327a5c115d9d9b2bba6fc", "sha256": "61f034932bf541af0c342ec4e39b2d5a326d20ca1c838151c1b5d8b906760c20" }, "downloads": -1, "filename": "django-entity-subscription-0.3.0.tar.gz", "has_sig": false, "md5_digest": "6207f104a7f327a5c115d9d9b2bba6fc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17783, "upload_time": "2014-07-15T19:52:14", "url": "https://files.pythonhosted.org/packages/a3/bf/98d9092e98e3cf4220cccfea7ab2accdba7b293a39e4313f3088c2b665e1/django-entity-subscription-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "1c7450947a53fe9a5c055e1950868359", "sha256": "c912b3ed947cc765294365d572485bcb5746f4f41bdf10db031f7040666a1f33" }, "downloads": -1, "filename": "django-entity-subscription-0.4.0.tar.gz", "has_sig": false, "md5_digest": "1c7450947a53fe9a5c055e1950868359", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18849, "upload_time": "2014-09-29T19:38:49", "url": "https://files.pythonhosted.org/packages/20/ed/cb03950295b4af2346fc7c044d73adfd8d8d7076cea0fa5d3584cda47ccd/django-entity-subscription-0.4.0.tar.gz" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "bff4ea96b7d842fb82ca0bf9b561ba4a", "sha256": "ee4b3a1a824c1cb0ef8e63b9fe03d7f9d7f62c8a11238733a30f8db5531d055c" }, "downloads": -1, "filename": "django-entity-subscription-0.4.1.tar.gz", "has_sig": false, "md5_digest": "bff4ea96b7d842fb82ca0bf9b561ba4a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18802, "upload_time": "2014-09-30T02:54:19", "url": "https://files.pythonhosted.org/packages/b3/36/3ee39a9177bbb3e2fb534b218d71ffe90719db3ed10ce9839cc04fcb5ae4/django-entity-subscription-0.4.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "bff4ea96b7d842fb82ca0bf9b561ba4a", "sha256": "ee4b3a1a824c1cb0ef8e63b9fe03d7f9d7f62c8a11238733a30f8db5531d055c" }, "downloads": -1, "filename": "django-entity-subscription-0.4.1.tar.gz", "has_sig": false, "md5_digest": "bff4ea96b7d842fb82ca0bf9b561ba4a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18802, "upload_time": "2014-09-30T02:54:19", "url": "https://files.pythonhosted.org/packages/b3/36/3ee39a9177bbb3e2fb534b218d71ffe90719db3ed10ce9839cc04fcb5ae4/django-entity-subscription-0.4.1.tar.gz" } ] }