Metadata-Version: 1.1
Name: django-field-history
Version: 0.7.0
Summary: A Django app to track changes to a model field.
Home-page: https://github.com/grantmcconnaughey/django-field-history
Author: Grant McConnaughey
Author-email: grantmcconnaughey@gmail.com
License: BSD
Description: ====================
        django-field-history
        ====================
        
        .. image:: https://badge.fury.io/py/django-field-history.svg
            :target: https://badge.fury.io/py/django-field-history
        
        .. image:: https://readthedocs.org/projects/django-field-history/badge/?version=latest
            :target: https://django-field-history.readthedocs.io/en/latest/?badge=latest
            :alt: Documentation Status
        
        .. image:: https://travis-ci.org/grantmcconnaughey/django-field-history.svg?branch=master
            :target: https://travis-ci.org/grantmcconnaughey/django-field-history
        
        .. image:: https://coveralls.io/repos/github/grantmcconnaughey/django-field-history/badge.svg?branch=master
            :target: https://coveralls.io/github/grantmcconnaughey/django-field-history?branch=master
        
        A Django app to track changes to a model field. For Python 2.7/3.4+ and Django 1.11/2.0+.
        
        Other similar apps are `django-reversion <https://github.com/etianen/django-reversion>`_ and `django-simple-history <https://github.com/treyhunner/django-simple-history>`_, which track *all* model fields.
        
        +------------------------+----------------------+------------------+----------------------------------+
        | Project                | django-field-history | django-reversion | django-simple-history            |
        +------------------------+----------------------+------------------+----------------------------------+
        | Admin Integration      | N/A                  | Yes              | Yes                              |
        +------------------------+----------------------+------------------+----------------------------------+
        | All/Some fields        | Some                 | Some             | All                              |
        +------------------------+----------------------+------------------+----------------------------------+
        | Object History         | No                   | Yes              | Yes                              |
        +------------------------+----------------------+------------------+----------------------------------+
        | Model History          | N/A                  | No               | Yes                              |
        +------------------------+----------------------+------------------+----------------------------------+
        | Multi-object Revisions | N/A                  | Yes              | No                               |
        +------------------------+----------------------+------------------+----------------------------------+
        | Extra Model Manager    | Yes                  | No               | Yes                              |
        +------------------------+----------------------+------------------+----------------------------------+
        | Model Registry         | No                   | Yes              | No                               |
        +------------------------+----------------------+------------------+----------------------------------+
        | Django View Helpers    | No                   | Yes              | No                               |
        +------------------------+----------------------+------------------+----------------------------------+
        | Manager Helper Methods | N/A                  | Yes              | Yes (``as_of``, ``most_recent``) |
        +------------------------+----------------------+------------------+----------------------------------+
        | MySQL Support          | Extra config         | Complete         | Complete                         |
        +------------------------+----------------------+------------------+----------------------------------+
        
        Documentation
        -------------
        
        The full documentation is at https://django-field-history.readthedocs.io.
        
        Features
        --------
        
        * Keeps a history of all changes to a particular model's field.
        * Stores the field's name, value, date and time of change, and the user that changed it.
        * Works with all model field types (except ``ManyToManyField``).
        
        Quickstart
        ----------
        
        Install django-field-history::
        
            pip install django-field-history
        
        Be sure to put it in INSTALLED_APPS.
        
        .. code-block:: python
        
            INSTALLED_APPS = [
                # other apps...
                'field_history',
            ]
        
        Then add it to your models.
        
        .. code-block:: python
        
            from field_history.tracker import FieldHistoryTracker
        
            class PizzaOrder(models.Model):
                STATUS_CHOICES = (
                    ('ORDERED', 'Ordered'),
                    ('COOKING', 'Cooking'),
                    ('COMPLETE', 'Complete'),
                )
                status = models.CharField(max_length=64, choices=STATUS_CHOICES)
        
                field_history = FieldHistoryTracker(['status'])
        
        Now each time you change the order's status field information about that change will be stored in the database.
        
        .. code-block:: python
        
            from field_history.models import FieldHistory
        
            # No FieldHistory objects yet
            assert FieldHistory.objects.count() == 0
        
            # Creating an object will make one
            pizza_order = PizzaOrder.objects.create(status='ORDERED')
            assert FieldHistory.objects.count() == 1
        
            # This object has some fields on it
            history = FieldHistory.objects.get()
            assert history.object == pizza_order
            assert history.field_name == 'status'
            assert history.field_value == 'ORDERED'
            assert history.date_created is not None
        
            # You can query FieldHistory using the get_{field_name}_history()
            # method added to your model
            histories = pizza_order.get_status_history()
            assert list(FieldHistory.objects.all()) == list(histories)
        
            # Or using the custom FieldHistory manager
            histories2 = FieldHistory.objects.get_for_model_and_field(pizza_order, 'status')
            assert list(histories) == list(histories2)
        
            # Updating that particular field creates a new FieldHistory
            pizza_order.status = 'COOKING'
            pizza_order.save()
            assert FieldHistory.objects.count() == 2
        
            updated_history = histories.latest()
            assert updated_history.object == pizza_order
            assert updated_history.field_name == 'status'
            assert updated_history.field_value == 'COOKING'
            assert updated_history.date_created is not None
        
        Management Commands
        -------------------
        
        django-field-history comes with a few management commands.
        
        createinitialfieldhistory
        +++++++++++++++++++++++++
        
        This command will inspect all of the models in your application and create ``FieldHistory`` objects for the models that have a ``FieldHistoryTracker``. Run this the first time you install django-field-history.
        
        ::
        
            python manage.py createinitialfieldhistory
        
        renamefieldhistory
        ++++++++++++++++++
        
        Use this command after changing a model field name of a field you track with ``FieldHistoryTracker``::
        
            python manage.py renamefieldhistory --model=app_label.model_name --from_field=old_field_name --to_field=new_field_name
        
        For instance, if you have this model:
        
        .. code-block:: python
        
            class Person(models.Model):
                username = models.CharField(max_length=255)
        
                field_history = FieldHistoryTracker(['username'])
        
        And you change the ``username`` field name to ``handle``:
        
        .. code-block:: python
        
            class Person(models.Model):
                handle = models.CharField(max_length=255)
        
                field_history = FieldHistoryTracker(['handle'])
        
        You will need to also update the ``field_name`` value in all ``FieldHistory`` objects that point to this model::
        
            python manage.py renamefieldhistory --model=myapp.Person --from_field=username --to_field=handle
        
        Storing Which User Changed the Field
        ------------------------------------
        
        There are two ways to store the user that changed your model field. The simplest way is to use **the logged in user** that made the request. To do this, add the ``FieldHistoryMiddleware`` class to your ``MIDDLEWARE`` setting.
        
        .. code-block:: python
        
            MIDDLEWARE = [
                'django.contrib.sessions.middleware.SessionMiddleware',
                'django.middleware.common.CommonMiddleware',
                'django.contrib.auth.middleware.AuthenticationMiddleware',
                'field_history.middleware.FieldHistoryMiddleware',
            ]
        
        Alternatively, you can add a ``_field_history_user`` property to the model that has fields you are tracking. This property should return the user you would like stored on ``FieldHistory`` when your field is updated.
        
        .. code-block:: python
        
            class Pizza(models.Model):
                name = models.CharField(max_length=255)
                updated_by = models.ForeignKey('auth.User')
        
                field_history = FieldHistoryTracker(['name'])
        
                @property
                def _field_history_user(self):
                    return self.updated_by
        
        Working with MySQL
        ------------------
        
        If you're using MySQL, the default configuration will throw an exception when you run migrations. (By default, ``FieldHistory.object_id`` is implemented as a ``TextField`` for flexibility, but indexed columns in MySQL InnoDB tables may be a maximum of 767 bytes.) To fix this, you can set ``FIELD_HISTORY_OBJECT_ID_TYPE`` in settings.py to override the default field type with one that meets MySQL's constraints. ``FIELD_HISTORY_OBJECT_ID_TYPE`` may be set to either:
        
        1. the Django model field class you wish to use, or
        2. a tuple ``(field_class, kwargs)``, where ``field_class`` is a Django model field class and ``kwargs`` is a dict of arguments to pass to the field class constructor.
        
        To approximate the default behavior for Postgres when using MySQL, configure ``object_id`` to use a ``CharField`` by adding the following to settings.py:
        
        .. code-block:: python
        
            from django.db import models
            FIELD_HISTORY_OBJECT_ID_TYPE = (models.CharField, {'max_length': 100})
        
        ``FIELD_HISTORY_OBJECT_ID_TYPE`` also allows you to use a field type that's more efficient for your use case, even if you're using Postgres (or a similarly unconstrained database). For example, if you always let Django auto-create an ``id`` field (implemented internally as an ``AutoField``), setting ``FIELD_HISTORY_OBJECT_ID_TYPE`` to ``IntegerField`` will result in efficiency gains (both in time and space). This would look like:
        
        .. code-block:: python
        
            from django.db import models
            FIELD_HISTORY_OBJECT_ID_TYPE = models.IntegerField
        
        Running Tests
        -------------
        
        Does the code actually work?
        
        ::
        
            source <YOURVIRTUALENV>/bin/activate
            (myenv) $ pip install -r requirements-test.txt
            (myenv) $ python runtests.py
        
        
        
        
        History
        -------
        
        0.7.0 (September 3, 2018)
        ++++++++++++++++++++
        * Added support for Django 2.0 and 2.1
        * Added support for Python 3.7
        * Dropped support for Django 1.7 through 1.10
        * Dropped support for Python 3.2 and 3.3
        * Fixed generic primary key bug with `createinitialfieldhistory` command (#20)
        
        0.6.0 (December 22, 2016)
        +++++++++++++++++++++++++
        * Added Django 1.10 compatibility.
        * Added MySQL compatibility.
        * Fixed issue that would duplicate tracked fields.
        
        0.5.0 (April 16, 2016)
        ++++++++++++++++++++++
        * Added the ability to track field history of parent models.
        * Added Django 1.7 compatibility.
        
        0.4.0 (February 24, 2016)
        +++++++++++++++++++++++++
        * Added a way to automatically store the logged in user on ``FieldHistory.user``.
        
        0.3.0 (February 20, 2016)
        +++++++++++++++++++++++++
        
        * ``FieldHistory`` objects are now created using ``bulk_create``, which means only one query will be executed, even when changing multiple fields at the same time.
        * Added a way to store which user updated a field.
        * Added ``get_latest_by`` to ``FieldHistory`` Meta options so ``.latest()`` and ``.earliest()`` can be used.
        * Added ``createinitialfieldhistory`` management command.
        * Added ``renamefieldhistory`` management command.
        
        0.2.0 (February 17, 2016)
        +++++++++++++++++++++++++
        
        * First release on PyPI.
        
Keywords: django-field-history
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Framework :: Django :: 1.11
Classifier: Framework :: Django :: 2.0
Classifier: Framework :: Django :: 2.1
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
