Metadata-Version: 1.1
Name: django-spectator
Version: 8.6.0
Summary: A Django app to track book reading, movie viewing, gig going, play watching, etc.
Home-page: https://github.com/philgyford/django-spectator
Author: Phil Gyford
Author-email: phil@gyford.com
License: MIT
Description: ==================
         Django Spectator
        ==================
        
        .. image:: https://travis-ci.org/philgyford/django-spectator.svg?branch=master
          :target: https://travis-ci.org/philgyford/django-spectator?branch=master
        
        .. image:: https://coveralls.io/repos/github/philgyford/django-spectator/badge.svg?branch=master
          :target: https://coveralls.io/github/philgyford/django-spectator?branch=master
        
        Two Django apps:
        
        * One to track book and periodical reading, including start and end dates, authors.
        * One to track events attended (movie, plays, gigs, exhibitions, comedy, dance,
          classical), including date, venue, and people/organisations involved.
        
        For Django 1.11.x or Django 2.0.x running on Python 3.5 or 3.6.
        
        It has URLs, views and templates to create a site displaying all the data, and
        Django admin screens to add and edit them. The templates use `Bootstrap v4.1 <https://getbootstrap.com>`_.
        
        There are also template tags for displaying data in your own templates (see
        below).
        
        
        ************
        Installation
        ************
        
        Install with pip::
        
            pip install django-spectator
        
        Add the apps to your project's ``INSTALLED_APPS`` in ``settings.py``::
        
            INSTALLED_APPS = [
                ...
                'spectator.core',
                'spectator.events',
                'spectator.reading',
            ]
        
        While ``spectator.core`` is required, you can omit either ``spectator.events``
        or ``spectator.reading`` if you only want to use one of them.
        
        Run migrations::
        
            ./manage.py migrate
        
        Add to your project's ``urls.py``::
        
            urlpatterns = [
                # ...
        
                url(r'^spectator/', include('spectator.core.urls')),
            ]
        
        You can change the initial path (``r'^spectator/'``) to whatever suits you. e.g.
        use ``r'^'`` to have Spectator's home page be the front page of your site.
        
        Then, go to Django Admin to add your data.
        
        
        Settings
        ========
        
        There are a few optional settings that can be used in your project's
        ``settings.py`` file. This is the full list, with their defaults. Descriptions
        of each are below::
        
            SPECTATOR_GOOGLE_MAPS_API_KEY = ''
        
            SPECTATOR_SLUG_ALPHABET = 'abcdefghijkmnopqrstuvwxyz23456789'
        
            SPECTATOR_SLUG_SALT = 'Django Spectator'
        
            SPECTATOR_READING_DATE_PERIOD_FORMAT_SHORT = '{}–{}'
        
            SPECTATOR_READING_DATE_PERIOD_FORMAT_LONG = '{} to {}'
        
            SPECTATOR_READING_DATE_FORMAT = '%-d %b %Y'
        
            SPECTATOR_READING_DATE_YEAR_FORMAT = '%Y'
        
            SPECTATOR_READING_DATE_MONTH_FORMAT = '%b'
        
            SPECTATOR_READING_DATE_DAY_FORMAT = '%-d'
        
            SPECTATOR_READING_DATE_YEAR_MONTH_FORMAT = '%b %Y'
        
            SPECTATOR_READING_DATE_MONTH_DAY_FORMAT = '%-d %b'
        
            SPECTATOR_EVENTS_DATE_FORMAT = '%-d %b %Y'
        
        General settings
        ----------------
        
        If you get a `Google Maps JavaScript API key <https://developers.google.com/maps/documentation/javascript/get-api-key>`_ and
        add it to the settings, it will enable using a map in the Django Admin to set
        the location of Venues, and the displaying of Venues' maps in the public
        templates::
        
            SPECTATOR_GOOGLE_MAPS_API_KEY = 'YOUR-API-KEY'
        
        URLs for all objects include automatically-generated slugs, which are based on
        [Hashids](http://hashids.org) of the object's ID. You can change which
        characters are used in these slugs with this setting. e.g.::
        
            SPECTATOR_SLUG_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
        
        You can also change the salt value used to encode the slugs. While the slugs
        don't provide complete security (i.e. it's not impossible to determine the ID on
        which a slug is based), using your own salt value can't hurt. e.g.::
        
            SPECTATOR_SLUG_SALT = 'My special salt value is here'
        
        Reading settings
        ----------------
        
        You can change the way the dates of publication readings are displayed. This is
        a bit fiddly because there are so many ways to represent such periods, e.g.:
        
        * 6 Feb 2017
        * 1–6 Feb 2017
        * 2017–2018
        * 1 Feb to 3 Mar 2017
        * Feb 2017 to Mar 2018
        
        First, you can set the formatting used to display periods between two dates, no
        matter how those dates are represented::
        
            SPECTATOR_READING_DATE_PERIOD_FORMAT_SHORT = '{}–{}'
        
            SPECTATOR_READING_DATE_PERIOD_FORMAT_LONG = '{} to {}'
        
        Then you can set the formatting (based on `strftime <http://strftime.org>`_) for
        the different kinds of dates represented::
        
            # e.g. "8 Apr 2018"
            SPECTATOR_READING_DATE_FORMAT = '%-d %b %Y'
        
            # e.g. "2018"
            SPECTATOR_READING_DATE_YEAR_FORMAT = '%Y'
        
            # e.g. "Apr"
            SPECTATOR_READING_DATE_MONTH_FORMAT = '%b'
        
            # e.g. "8"
            SPECTATOR_READING_DATE_DAY_FORMAT = '%-d'
        
            # e.g. "Apr 2018"
            SPECTATOR_READING_DATE_YEAR_MONTH_FORMAT = '%b %Y'
        
        Events settings
        ---------------
        
        There is one optional setting to for the format of dates used when displaying
        an event, using `strftime <http://strftime.org>`_ format::
        
        
            # e.g. "8 Apr 2018"
            SPECTATOR_EVENTS_DATE_FORMAT = '%-d %b %Y'
        
        
        ********
        Overview
        ********
        
        There are two main parts to Spectator: Reading and Events (movies, gigs, etc). They both share Creators.
        
        Creators
        ========
        
        Creators are the authors of books, directors of movies, actors in plays, groups who perfom at gigs, etc.
        
        A Creator has a name and a ``kind``, of either "individual" (e.g. "Anthony Sher") or "group" (e.g. "Royal Shakespeare Company").
        
        A Creator is associated with books, movies, events, etc. through roles, which
        include an optional ``role_name`` such as "Author", "Illustrator", "Director",
        "Playwright", "Company", etc. The roles can be given an order so that the
        creators of a thing will be listed in the appropriate order (such as the
        director before a movie's actors).
        
        See ``spectator/models/core.py`` for these models.
        
        Reading
        =======
        
        A Publication is a thing that's been read, and has a ``kind`` of either "book"
        or "periodical". A Publication can optionally be part of a PublicationSeries.
        e.g. a Publication "Vol. 3 No. 7 September 2005" could be part of the "The
        Believer" PublicationSeries.
        
        A Publication can have zero or more Readings. A Reading can have
        a ``start_date`` and ``end_date``. If the ``start_date`` is set but the
        ``end_date`` isn't, the Publication is currently being read. When a Reading has
        been completed, and an ``end_date`` added, it can be marked as ``is_finished``
        or not. If not, it's because you gave up on the Publication before getting to
        the end.
        
        Both ``start_date`` and ``end_date`` indicates a specific day by default. If
        you don't know the day, or the month, a granularity can be specified indicating
        whether the reading started/ended sometime during the month or year.
        
        See ``spectator/models/reading.py`` for these models.
        
        Events
        ======
        
        An Event specifies a date on which you saw a thing at a particular Venue.
        
        A Venue has a name and, optionally, location details.
        
        Each Event can have zero or more Creators associated directly with it. e.g. the
        performers at a gig, the comedians at a comedy event. These can be in a specific
        order, and each with an optional role. e.g:
        
        * The Wedding Present
            * Role: Headliner
            * Order: 1
        * Buffalo Tom
            * Role: Support
            * Order: 2
        
        Events can be different kinds, e.g. "gig", "cinema", "theatre". This is only used for categorising Events into different lists - it doesn't restrict the kinds of Works that can be associated with it. You could have a "cinema" Event that has a movie, play and dance piece associated with it.
        
        Each Event can have zero or more Works associated with it: movies, plays, classical works or dance pieces. Each Work can have zero or more Creators, each with optional roles, associated directly with it. e.g. "Wolfgang Amadeus Mozart (Composer)",
        "William Shakespeare (Playwright)" or "Steven Spielberg (Director)":
        
        Events can be given an optional title (e.g. "Glastonbury Festival"). If a title
        isn't specified one is created automatically when needed, based on any Works
        associated with it, or else any Creators associated with it.
        
        
        *************
        Template tags
        *************
        
        Each app, `core`, `events` and `reading`, has some template tags.
        
        Core template tags
        ==================
        
        To use any of these in a template, first::
        
            {% load spectator_core %}
        
        Most Read Creators
        ------------------
        
        To get a QuerySet of Creators with the most Readings associated with them::
        
            {% most_read_creators num=10 %}
        
        Each Creator will have a ``num_readings`` attribute. It will only include
        Creators whose role on a publication was "Author" or was left blank. i.e.
        Creators who were "Illustrator" or "Translator" would not be counted.
        
        To display this as a chart in a Bootstrap card::
        
            {% most_read_creators_card num=10 %}
        
        This will exclude any Creators with only 1 Reading.
        
        Most Visited Venues
        -------------------
        
        To get a QuerySet of Venues with the most Events associated with them::
        
            {% most_visited_venues num=10 %}
        
        Each Venue will have a ``num_visits`` attribute.
        
        To display this as a chart in a Bootstrap card::
        
            {% most_visited_venues_card num=10 %}
        
        This will exclude any Venues with only 1 Event.
        
        
        Reading template tags
        =====================
        
        To use any of these in a template, first::
        
            {% load spectator_reading %}
        
        In-progress Publications
        ------------------------
        
        To get a QuerySet of Publications currently being read use
        ``in_progress_publications``::
        
            {% in_progress_publications as publications %}
        
            {% for pub in publications %}
                <p>{{ pub }}<br>
                {% for role in pub.roles.all %}
                    {{ role.creator.name }}
                    {% if role.role_name %}({{ role.role_name }}){% endif %}
                    <br>
                {% endfor %}
                </p>
            {% endfor %}
        
        Or to display as a Bootstrap card::
        
            {% in_progress_publications_card %}
        
        Publications being read on a day
        --------------------------------
        
        To get a QuerySet of Publications that were being read on a particular day use
        ``day_publications``. If ``my_date`` is a python ``date`` object::
        
            {% day_publications date=my_date as publications %}
        
        And display the results as in the above example.
        
        Or to display as a Bootstrap card::
        
            {% day_publications_card date=my_date %}
        
        Years of reading
        ----------------
        
        To get a QuerySet of the years in which Publications were being read::
        
            {% reading_years as years %}
        
            {% for year in years %}
                {{ year|date:"Y" }}<br>
            {% endfor %}
        
        Or to display as a Bootstrap card, with each year linking to the
        ``ReadingYearArchiveView``::
        
            {% reading_years_card current_year=year %}
        
        Here, ``year`` is a date object indicating a year which shouldn't be linked.
        
        Annual reading counts
        ---------------------
        
        For more detail than the ``reading_years`` tag, use this to get the number of
        Books, and Periodicals (and the total) finished per year::
        
            {% annual_reading_counts as years %}
        
            {% for year_data in years %}
                {{ year_data.year }}:
                {{ year_data.book }} book(s),
                {{ year_data.periodical }} periodical(s),
                {{ year_data.total }} total.<br>
            {% endfor %}
        
        Or to display as a Bootstrap card, with each year linking to ``ReadingYearArchiveView``::
        
            {% annual_reading_counts_card current_year=year kind='all' %}
        
        Here, ``year`` is a date object indicating a year which shouldn't be linked.
        
        And ``kind`` can be one of "all" (default), "book" or "periodical". If it's "all",
        then the result is rendered as a table, with a column each for year, book count,
        periodical count and total count. Otherwise it's a list of years with the
        book/periodical counts in parentheses.
        
        
        Events template tags
        ====================
        
        To use any of these in a template, first::
        
            {% load spectator_events %}
        
        Recent Events
        -------------
        
        To get a QuerySet of Events that happened recently::
        
            {% recent_events num=3 as events %}
        
            {% for event in events %}
                <p>
                    {{ event }}<br>
                    {{ event.venue.name }}
                </p>
            {% endfor %}
        
        If ``num`` is not specified, 10 are returned by default.
        
        Or to display as a Boostrap card::
        
            {% recent_events_card num=3 %}
        
        Events on a day
        ---------------
        
        To get a QuerySet of Events that happened on a particular day, use
        ``day_events``. If ``my_date`` is a python ``date`` object::
        
            {% day_events date=my_date as events %}
        
        And display the results as in the above example.
        
        Or to display as a Bootstrap card::
        
            {% day_events_card date=my_date %}
        
        Years of Events
        ---------------
        
        To get a QuerySet of the years in which Events happened::
        
            {% events_years as years %}
        
            {% for year in years %}
                {{ year|date:"Y" }}<br>
            {% endfor %}
        
        Or to display as a Bootstrap card, with each year linking to the
        ``EventYearArchiveView``::
        
            {% events_years_card current_year=year %}
        
        Here, ``year`` is a date object indicating a year which shouldn't be linked.
        
        Annual Event Counts
        -------------------
        
        To include counts of Events per year::
        
            {% annual_event_counts as years %}
        
            {% for year_data in years %}
                {{ year_data.year|date:"Y" }}: {{ year_data.total }} event(s)<br>
            {% endfor %}
        
        Restrict to one kind of Event::
        
            {% annual_event_counts kind='cinema' as years %}
        
        Or to display as a Bootstrap card, with each year linking to ``EventYearArchiveView``::
        
            {% annual_event_counts_card current_year=year kind='all' %}
        
        Here, ``year`` is a date object indicating a year which shouldn't be linked.
        
        Most Seen Creators
        ------------------
        
        To get a QuerySet of Creators involved with the most Events::
        
            {% most_seen_creators num=10 event_kind='gig' %}
        
        Each Creator will have a ``num_events`` attribute.
        
        ``event_kind`` can be omitted, or be ``None`` to include all kinds of Event.
        
        To display this as a chart in a Bootstrap card::
        
            {% most_seen_creators_card num=10 event_kind='gig' %}
        
        This will exclude any Creators with only 1 Event.
        
        Creators With Most Works
        ------------------------
        
        To get a QuerySet of Creators that have the most Works (e.g, movies, plays, etc)::
        
            {% most_seen_creators_by_works num=10 work_kind='movie', role_name='Director' %}
        
        Each Creator will have a ``num_works`` attribute.
        
        ``work_kind`` can be omitted and all kinds of Work will be counted.
        
        ``role_name`` can be omitted and all roles will be counted.
        
        The above example would, for each Creator, only count movie Works on which their
        role was 'Director'.
        
        To display this as a chart in a Bootstrap card::
        
            {% most_seen_creators_by_works_card num=10 work_kind='movie', role_name='Director' %}
        
        This will exclude any Creators with only 1 Work.
        
        
        Most Seen Works
        ---------------
        
        To get a QuerySet of Works involved with the most Events::
        
            {% most_seen_works num=10 kind='movie' %}
        
        Each Work will have a ``num_views`` attribute.
        
        ``kind`` can be omitted, or be ``None`` to include all kinds of Work.
        
        To display this as a chart in a Bootstrap card::
        
            {% most_seen_works_card num=10 kind='movie' %}
        
        This will exclude any Works with only 1 Event.
        
        
        *****************
        Local development
        *****************
        
        ``devproject/`` is a basic Django project to use the app locally. Use it like::
        
        $ pip install -r devproject/requirements.txt
        $ python setup.py develop
        $ ./devproject/manage.py migrate
        $ ./devproject/manage.py runserver
        
        Run tests with tox. Install it with::
        
        $ pip install tox
        
        Run all tests in all environments like::
        
        $ tox
        
        To run tests in only one environment, specify it. In this case, Python 3.6 and Django 2.0::
        
        $ tox -e py36-django20
        
        To run a specific test, add its path after ``--``, eg::
        
        $ tox -e py36-django20 -- tests.core.test_models.CreatorTestCase.test_ordering
        
        Running the tests in all environments will generate coverage output. There will also be an ``htmlcov/`` directory containing an HTML report. You can also generate these reports without running all the other tests::
        
        $ tox -e coverage
        
        Making a new release
        ====================
        
        So I don't forget...
        
        1. Put new changes on ``master``.
        2. Update the ``__version__`` in ``spectator.__init__.py``.
        3. Update ``CHANGES.rst``.
        4. Do ``python setup.py tag``.
        5. Do ``python setup.py publish``.
        
        
        Adding a new Event kind
        =======================
        
        If it's simple (like, Gigs, Comedy, etc.) and doesn't require any specific kind of Works, then:
        
        * In ``spectator.events.models.Event`` add it in ``KIND_CHOICES`` and ``KIND_SLUGS``.
        * Possibly add a special case for it in ``Event.get_kind_name_plural()``.
        * Add a simple factory for it in ``spectator.events.factories``.
        * In ``tests.events.test_models.EventTestCase``:
            * Add it to:
                * ``test_get_kind()``
                * ``test_valid_kind_slugs()``
                * ``test_kind_slug()``
                * ``test_kind_name()``
                * ``test_kind_name_plural()``
                * ``test_get_kinds_data()``
            * Add a ``test_absolute_url_*()`` test for this kind.
        
        
        Adding a new Work kind
        ======================
        
        * In ``spectator.events.models.Work`` add it in ``KIND_CHOICES`` and ``KIND_SLUGS``.
        * On the ``Event`` model add a new method similar to ``get_classical_works()`` for this new kind of ``Work``.
        * On the ``spectator.core.models.Creator`` model add a new method similar to ``get_classical_works()`` for this new kind of ``Work``.
        * Add a simple factory for it in ``spectator.events.factories``.
        * In ``spectator/events/templates/spectator_events/event_detail.html`` add an include to list the
          works.
        * In ``spectator/core/templates/spectator_core/creator_detail.html`` add an include to
          list the works.
        * In ``tests/`` add equivalents of:
            * ``core.test_models.CreatorTestCase.test.get_classical_works()``
            * ``events.test_models.EventTestCase.test_get_classical_works()``
            * ``events.test_models.WorkTestCase.test_absolute_url_classicalwork()``
            * ``events.test_models.WorkTestCase.test_get_list_url_classicalwork()``
        
        
        *******
        Contact
        *******
        
        * Phil Gyford
        * phil@gyford.com
        * @philgyford on Twitter
        
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 1.11
Classifier: Framework :: Django :: 2.0
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
