{ "info": { "author": "drozdowsky", "author_email": "hdrozdow+github@pm.me", "bugtrack_url": null, "classifiers": [], "description": "# Django Tracking Model \ud83c\udfc1\nTrack changes made to your model's instance. \nChanges are cleared on save. \nThis package is intented to be used mainly with signals. \nMutable fields (e.g. JSONField) are not handled with deepcopy to keep it fast and simple. \nMeant to be model_utils's FieldTracker fast alternative.\n\n*Available on [PyPi](https://pypi.org/project/django-tracking-model/)* \n\n\n## Usage\n```python\nfrom django.db import models\nfrom tracking_model import TrackingModelMixin\n\n# order matters\nclass Example(TrackingModelMixin, models.Model)\n text = models.TextField(null=True)\n myself = models.ForeignKey(\"self\", null=True)\n array = models.ArrayField(TextField())\n```\n```python\nIn [1]: e = Example.objects.create(id=1, text=\"Sample Text\")\nIn [2]: e.tracker.changed, e.tracker.newly_created\nOut[1]: ({}, True)\nIn [3]: e.text = \"Different Text\"\nIn [4]: e.tracker.changed\nOut[2]: {\"text\": \"Sample Text\"}\nIn [5]: e.save()\nIn [6]: e.tracker.changed, e.tracker.newly_created\nOut[3]: ({}, False)\n```\nDTM will also detect changes made to ForeignKey/OneToOne fields\n```python\nIn [1]: Example.objects.create(myself=e)\nIn [2]: e.myself = None\nIn [3]: e.tracker.changed\nOut[1]: {\"myself_id\": 1}\n```\nBecause DTM does not handle mutable fields well, you handle them with copy/deepcopy.\n```python\nIn [1]: e = Example.objects.create(array=['I', 'am', 'your'])\nIn [2]: copied = copy(e.array)\nIn [3]: copied.append('father')\nIn [4]: e.array = copied\nIn [5]: e.tracker.changed\nOut[1]: {'array': ['I', 'am', 'your', 'father']}\nIn [6]: e.array = ['Testing', 'is', 'the', 'future'] # in this case copy not needed\n```\nDTM works best with \\*\\_save signals\n```python\ndef pre_save_example(instance, *args, **kwargs):\n # .create() does not populate .changed, we use newly_created\n if 'text' in instance.tracker.changed or instance.tracker.newly_created:\n if instance.text\n instance.array = instance.text.split()\n\npre_save.connect(pre_save_example, sender=Example)\n```\n```python\nIn [1]: e = Example.objects.create(text='I am your father')\nIn [2]: e.refresh_from_db() # not needed\nIn [3]: e.array\nOut[1]: ['I', 'am', 'your', 'father']\n```\nDTM handles deferred fields well\n```python\nIn [1]: e = Example.objects.only('array').first()\nIn [2]: e.text = 'I am not your father' \nIn [3]: e.tracker.changed\nOut[4]: {'text': DeferredAttribute}\n```\nYou narrow choice of fields that should be tracked. By default everything is tracked\n```python\nclass Example(models.Model):\n TRACKED_FIELDS = ['first']\n first = models.TextField()\n second = models.TextField()\n```\n\n## Requirements\n * Python >= 2.7, <= 3.7\n * Django >= 1.9, <= 2.2\n\n## Todo\n- [ ] Tests could be more readable\n- [ ] Signals decorators", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/drozdowsky/django-tracking-model/", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "django-tracking-model", "package_url": "https://pypi.org/project/django-tracking-model/", "platform": "", "project_url": "https://pypi.org/project/django-tracking-model/", "project_urls": { "Homepage": "https://github.com/drozdowsky/django-tracking-model/" }, "release_url": "https://pypi.org/project/django-tracking-model/0.1.1/", "requires_dist": null, "requires_python": "", "summary": "Track changes made to django model instance.", "version": "0.1.1" }, "last_serial": 5440535, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "e7a962f7cb78925a491952008b280a80", "sha256": "ac06d6623be1a7d8e9fe63af29cbecfe0b626b4af01cd113c2dff8c0c75202e9" }, "downloads": -1, "filename": "django_tracking_model-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e7a962f7cb78925a491952008b280a80", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 3943, "upload_time": "2019-06-19T10:21:46", "url": "https://files.pythonhosted.org/packages/fe/50/3059b9ab3ccfa63fe7e5fd4cbe8f3d36f07650e0213c72f0be9df3616c53/django_tracking_model-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "31fc1015f3e73981003783ebc76567c3", "sha256": "d6f1e05d36d51269cec394b6e00466a5795ba1da9a388982551f66c1fa1a9e48" }, "downloads": -1, "filename": "django-tracking-model-0.1.0.tar.gz", "has_sig": false, "md5_digest": "31fc1015f3e73981003783ebc76567c3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5178, "upload_time": "2019-06-19T10:21:48", "url": "https://files.pythonhosted.org/packages/65/c9/2dd3c1e0cf3bae64ab6fa2b176cedad3d6e6719b4a745b34a5383af9c2cc/django-tracking-model-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "196ae6bf6efbc7ade923c20d85ca80a4", "sha256": "4614be5494fc45485c0b445524eeae716a1b878a53bf44e9b83c976efdfd79f4" }, "downloads": -1, "filename": "django-tracking-model-0.1.1.tar.gz", "has_sig": false, "md5_digest": "196ae6bf6efbc7ade923c20d85ca80a4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5686, "upload_time": "2019-06-24T12:52:05", "url": "https://files.pythonhosted.org/packages/c8/11/537e7c6d0571f81608f09538f24e3274bdae17f4488d695bdaaf07f0f8a8/django-tracking-model-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "196ae6bf6efbc7ade923c20d85ca80a4", "sha256": "4614be5494fc45485c0b445524eeae716a1b878a53bf44e9b83c976efdfd79f4" }, "downloads": -1, "filename": "django-tracking-model-0.1.1.tar.gz", "has_sig": false, "md5_digest": "196ae6bf6efbc7ade923c20d85ca80a4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5686, "upload_time": "2019-06-24T12:52:05", "url": "https://files.pythonhosted.org/packages/c8/11/537e7c6d0571f81608f09538f24e3274bdae17f4488d695bdaaf07f0f8a8/django-tracking-model-0.1.1.tar.gz" } ] }