{ "info": { "author": "Ha Junsoo", "author_email": "kuc2477@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.4" ], "description": "*************\ndjango-record\n*************\n.. image:: https://img.shields.io/pypi/l/django-record.svg\n :target: https://img.shields.io/pypi/django-record\n.. image:: https://secure.travis-ci.org/kuc2477/django-record.png?branch=master\n :target: http://travis-ci.org/kuc2477/django-record\n.. image:: https://coveralls.io/repos/kuc2477/django-record/badge.svg?branch=master\n :target: https://coveralls.io/r/kuc2477/django-record?branch=master\n.. image:: https://img.shields.io/pypi/v/django-record.svg\n :target: https://img.shields.io/pypi/django-record\n.. image:: https://img.shields.io/pypi/dm/django-record.svg\n :target: https://img.shields.io/pypi/django-record\n :alt: Latest Version\n\n\nAuthor\n======\n* `Ha Junsoo `_\n\n\nRequirements\n============\n* Tested against Python 2.7 and 3.4\n* *django-record* supports `django `_ 1.7 or later.\n* Requires `pandas `__ 0.17.0 or later.\n* Requires `faker `_ for tests.\n\n\nInstallation\n============\n``pip install django-record``\n\n\nRationale\n=========\nOften there are situations where you want to record your properties of your models and\nwhere you want to track their changes. Although that recording process can be implemented\nby `handcrafted, ad-hoc signals`_ or `overriding save() methods of your models`_, it's\nnot a generic way, and **it'll eventually mess up your code base**.\n\n*django-record* **automatically creates an snapshot-like extra record** when an audited \nDjango model instance has been changed **either directly or indirectly**,\nwithout messing up your code base.\n\n``RecordModel`` will detect any changes in ``recording_fields`` of\n``recording_model`` at it's ``post_save`` time or ``auditing_relatives``'s\n``post_save`` time and create an new record for it. \n\nYou can access records via record manager ``records`` in your recorded model\ninstance. You can also access recorded model's instance via ``recording``, \nwhich is in effect just ordinary ``ForeignKey``, from your records.\n\nMore conveniently, **just mix** ``RecordedModelMixin`` into your model and provide \n``recording_fields`` and ``auditing_relatives``.\n\n.. _`handcrafted, ad-hoc signals`: https://djangosnippets.org/snippets/500/\n.. _`overriding save() methods of your models`: https://trickveda.wordpress.com/2014/01/22/overriding-save-method-in-django-models/\n\n\nUsage\n=====\n.. code-block:: python\n\n from django.db import models\n from django_record.mixins import RecordedModelMixin\n\n\n class MyTopic(models.Model):\n title = models.CharField(max_length=100)\n\n\n class MyArticle(RecordedModelMixin, models.Model):\n topic = models.ForeignKey(MyTopic)\n text = models.TextField()\n\n @property\n def my_local_property(self):\n return self.text\n \n @property\n def my_nonlocal_property(self):\n return self.topic.title + self.text\n \n # We will monitor `topic` relative to watch if he changes!\n auditing_relatives = ['topic']\n\n recording_fields = [\n # Record changes of the model instance's `text` field\n 'text', \n # Yayy! we can record changes on properties too!\n ('my_local_property', models.TextField()),\n # Even indirect effects from relatives are recordable!\n ('my_nonlocal_property', models.TextField())\n ] \n\n\n # To get the model instance's all records\n >>> my_article.records.all()\n\n # To get queryset of the model instance's records created in specific \n # time threshold\n >>> my_article.records.created_in_years(2)\n >>> my_article.records.created_in_days(3)\n >>> my_article.records.created_in_minutes(5)\n\n # To resample records of today by hour\n >>> my_article.records.created_in_days().resample('T')\n\n # To get record contents\n >>> my_article.records.first().text\n >>> my_article.records.first().my_local_property\n >>> my_article.records.first().my_nonlocal_property\n\n\nNote\n====\n* **Recursive auditing is currently not supported.** Indirect effect only those \n from direct relatives will be detected and recorded.\n* **Only primitive types are supported for properties.** You must offer appropriate django field for them.\n* ``RecordModel`` is also a subclass of ``TimeStampedModel``, so make sure that\n you don't record either 'created' or 'modified' fields.\n\n\n=======\nChanges\n=======\n\n11.09.2015 (0.2.5 release)\n==========================\n* Renamed TimeStampedModel to AbstractTimeStampedModel.\n* Replaced monkey patched shortcut properties with ``RecordQueryset`` filters.\n Those shortcut properties are now deprecated.\n\n09.20.2015\n==========\n* Support Python 3.4\n\n06.13.2015\n==========\n* Following shortcut properties added to *recording_model*. All of properties\n below are ordinary django querysets.\n\n * ``records_in_hour``: Records created in last recent hour.\n * ``records_in_day``: Records created today.\n * ``records_in_week``: Records created in this week.\n * ``records_in_month``: Records created in this month.\n * ``records_in_year``: Records created in this year.\n\n* Following shortcut properties providing resampled records has been added to\n *recording_model*. All of properties below are ordinary django querysets.\n\n * ``resampled_records_in_hour``: Records created in last recent hour, \n resampled with minutes.\n * ``resampled_records_in_day``: Records created today, resampled with hours.\n * ``resampled_records_in_week``: Records created in this week, resamped with\n days.\n * ``resampled_records_in_month``: Records created in this month, resampled \n with days.\n * ``resamped_records_in_year``: Records created in this year, resampled with\n months.\n\n05.18.2015\n==========\n* ``RecordedModelMixin`` added.", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/kuc2477/django-record/", "keywords": "", "license": "GNU General Public License v2 (GPLv2)", "maintainer": "", "maintainer_email": "", "name": "django-record", "package_url": "https://pypi.org/project/django-record/", "platform": "OS Independent", "project_url": "https://pypi.org/project/django-record/", "project_urls": { "Homepage": "https://github.com/kuc2477/django-record/" }, "release_url": "https://pypi.org/project/django-record/0.2.5/", "requires_dist": null, "requires_python": "", "summary": "Models and mixins for recording changes in Django models", "version": "0.2.5" }, "last_serial": 1807227, "releases": { "0.1.2": [ { "comment_text": "", "digests": { "md5": "1d1370ad210b07955a8ec6e91090a21d", "sha256": "e6e55559327fa5d3434fcd54fe95e999d5012f983366d30857efa8ba59a46375" }, "downloads": -1, "filename": "django-record-0.1.2.tar.gz", "has_sig": false, "md5_digest": "1d1370ad210b07955a8ec6e91090a21d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4012, "upload_time": "2015-05-14T17:10:56", "url": "https://files.pythonhosted.org/packages/ae/a4/e1c7f91a817566654833bb5fe296633b1e7c83fa545a9c5b54cdcc9f8439/django-record-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "92d6e10469f8148c6b653f879ba92d3a", "sha256": "0bf727f371a143aa752bc77a7970ae510e6b35ed241436b897951ddba90fdfc0" }, "downloads": -1, "filename": "django-record-0.1.3.tar.gz", "has_sig": false, "md5_digest": "92d6e10469f8148c6b653f879ba92d3a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5468, "upload_time": "2015-05-14T17:16:45", "url": "https://files.pythonhosted.org/packages/52/30/3b6628b2bdb7dd152ec450cd6d64890ee8ddfdc5e6d2580e4207c1a542a3/django-record-0.1.3.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "3fdc7c9dbb9e37af154157c8504f960b", "sha256": "54b6605ec84a09d54517bfbdc74d48786912b4a98c7781eebce15d67e3e26f89" }, "downloads": -1, "filename": "django-record-0.1.5.tar.gz", "has_sig": false, "md5_digest": "3fdc7c9dbb9e37af154157c8504f960b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7336, "upload_time": "2015-05-17T13:02:27", "url": "https://files.pythonhosted.org/packages/4a/5e/c6509aafbfd3269727541fe2956181b07d4ba836baed0cdb952e1fc15c92/django-record-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "8af009c96404d76f483aa7c5df5a6723", "sha256": "1720ad54fd57019f568f051f8b820621712b06b36b4001b4f727ea740d668a91" }, "downloads": -1, "filename": "django-record-0.1.6.tar.gz", "has_sig": false, "md5_digest": "8af009c96404d76f483aa7c5df5a6723", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9403, "upload_time": "2015-05-18T08:00:42", "url": "https://files.pythonhosted.org/packages/ae/f3/c3e676cb7b4779e87f14db7698c3c16f8cf840e85db14252c65f426589d2/django-record-0.1.6.tar.gz" } ], "0.1.7": [ { "comment_text": "", "digests": { "md5": "e53a51ac4397a2025f2b857d2e44ae6b", "sha256": "4a69a98071352044b980f660fb9001c372d2fb5bb7a88de23ad2f7245b470a31" }, "downloads": -1, "filename": "django-record-0.1.7.tar.gz", "has_sig": false, "md5_digest": "e53a51ac4397a2025f2b857d2e44ae6b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9791, "upload_time": "2015-05-20T07:16:20", "url": "https://files.pythonhosted.org/packages/18/e1/f3c0d909cee811bc7809450f67923d74a3e3fae618c6b575520848c67ecf/django-record-0.1.7.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "68f3a6cff93a63f315221145f5ad77ed", "sha256": "5ccd20c2480a6b84fc129150d09d2e19077c4a3470673a2d6b18a1ecb684d91e" }, "downloads": -1, "filename": "django-record-0.2.0.tar.gz", "has_sig": false, "md5_digest": "68f3a6cff93a63f315221145f5ad77ed", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11736, "upload_time": "2015-06-13T03:29:37", "url": "https://files.pythonhosted.org/packages/83/e7/c0d37b8b0a146141dd2a938a7b52520aadaeb5097de38908b5575fa74525/django-record-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "44d74c44253a3dd3678368505df7b428", "sha256": "3fd14caa24d1423eae3451cd79db9622f174a9a415c71560bb2cc25351505498" }, "downloads": -1, "filename": "django-record-0.2.1.tar.gz", "has_sig": false, "md5_digest": "44d74c44253a3dd3678368505df7b428", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11733, "upload_time": "2015-06-13T07:09:41", "url": "https://files.pythonhosted.org/packages/2b/31/c280fc99d663447ace0c6a4e186cb2fe5d26f06f3827baf7827acd075d5b/django-record-0.2.1.tar.gz" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "dbf5482f1338e107008254bc8eb078dd", "sha256": "31a290d1d1424449f56007f265983a931d370f6907a5c92c5c0972e63b889561" }, "downloads": -1, "filename": "django-record-0.2.2.tar.gz", "has_sig": false, "md5_digest": "dbf5482f1338e107008254bc8eb078dd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11744, "upload_time": "2015-06-13T07:24:57", "url": "https://files.pythonhosted.org/packages/a6/c9/2e9197e8c7673d18a2bc197f317eef0a384df35aed1765e463927a60898f/django-record-0.2.2.tar.gz" } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "c928ee68b9afb83e68d4b103b38f10da", "sha256": "7312db36c66d95b724e3f8c479d0bce92197bbd9e38757504472598b090512a7" }, "downloads": -1, "filename": "django-record-0.2.3.tar.gz", "has_sig": false, "md5_digest": "c928ee68b9afb83e68d4b103b38f10da", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11794, "upload_time": "2015-09-04T22:52:28", "url": "https://files.pythonhosted.org/packages/4d/25/5960c588ad49cca05940c9f1e3b505c246ed97d904991b64cdb5dbd42610/django-record-0.2.3.tar.gz" } ], "0.2.4": [ { "comment_text": "", "digests": { "md5": "2bb63c9a6efa5670852f9d1a73aa1712", "sha256": "fb23cac777e8664e92740ac1ec557fb6b09369a5957e42618207a15401deaae6" }, "downloads": -1, "filename": "django-record-0.2.4.tar.gz", "has_sig": false, "md5_digest": "2bb63c9a6efa5670852f9d1a73aa1712", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11890, "upload_time": "2015-11-07T03:41:56", "url": "https://files.pythonhosted.org/packages/8b/08/384cf9e50331efa99ceb263242292b6af88b20dfd8b828f3552ac19459ce/django-record-0.2.4.tar.gz" } ], "0.2.5": [ { "comment_text": "", "digests": { "md5": "c173d8ea5a501717d89eff6d0c75d7b7", "sha256": "43c9ae95b157f7883b2622012a7e33faecd47b249b2f73648709aaf81ba3c52d" }, "downloads": -1, "filename": "django-record-0.2.5.tar.gz", "has_sig": false, "md5_digest": "c173d8ea5a501717d89eff6d0c75d7b7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10027, "upload_time": "2015-11-09T02:59:53", "url": "https://files.pythonhosted.org/packages/c7/51/07d1ddbaa1580d9bb9312ec71cd812523f63f92943dab526917663c8a29e/django-record-0.2.5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c173d8ea5a501717d89eff6d0c75d7b7", "sha256": "43c9ae95b157f7883b2622012a7e33faecd47b249b2f73648709aaf81ba3c52d" }, "downloads": -1, "filename": "django-record-0.2.5.tar.gz", "has_sig": false, "md5_digest": "c173d8ea5a501717d89eff6d0c75d7b7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10027, "upload_time": "2015-11-09T02:59:53", "url": "https://files.pythonhosted.org/packages/c7/51/07d1ddbaa1580d9bb9312ec71cd812523f63f92943dab526917663c8a29e/django-record-0.2.5.tar.gz" } ] }