Package: django-changeset
Django ChangeSetDjango ChangeSet is a simple Django app that will give your models the possibility to track all changes. It depends ondjango_userforeignkeyto determine the current user doing the change(s).Currently, Django 2.2 and 3.2 are supported and tested via GitHub Actions.Detailed documentation is in the docs subdirectory.Quick startUsepipto install and download django-changeset (anddjango-userforeignkey):pipinstalldjango-changesetAdddjango_userforeignkeyanddjango_changesetto yourINSTALLED_APPSlike this:INSTALLED_APPS=[...'django_userforeignkey','django_changeset',]Adddjango_userforeignkey.middleware.UserForeignKeyMiddlewareto yourMIDDLEWARElike this:MIDDLEWARE=(...'django.contrib.auth.middleware.AuthenticationMiddleware',...'django_userforeignkey.middleware.UserForeignKeyMiddleware',)Note: Make sure to insert theUserForeignKeyMiddlewareafterDjangosAuthenticationMiddleware.Example usageUseRevisionModelMixinas a mixin class for your models and add the fields you want to track in the metaconfiguration usingtrack_fieldsandtrack_related. Also add a generic relation toChangeSetusingchangesets = ChangeSetRelation():fromdjango.dbimportmodelsfromdjango_changeset.modelsimportRevisionModelMixinfromdjango_changeset.models.fieldsimportChangeSetRelationclassMyModel(models.Model,RevisionModelMixin):classMeta:track_fields=('my_data',)# track changes on my_datatrack_related=('my_ref',)# track changes on a related modelmy_data=models.CharField(max_length=64,verbose_name="Very important data you want to track")my_ref=models.ForeignKey('SomeOtherModel',verbose_name="Very important relation",related_name='my_models')# Generic Relation to ChangeSetchangesets=ChangeSetRelation()Note: If you want to have access to the propertiescreated_by,created_at,last_modified_by,last_modified_at,
you need to inherit fromCreatedModifiedByMixinaswell asRevisionModelMixin. For the Python MRO to work, you also
have to create an abstract base model:fromdjango.dbimportmodelsfromdjango_changeset.modelsimportCreatedModifiedByMixin,RevisionModelMixinfromdjango_changeset.models.fieldsimportChangeSetRelationclassBaseModel(models.Model):"""BaseModel is needed for proper MRO within Python/Django Models"""classMeta:abstract=TruepassclassMyModel(BaseModel,RevisionModelMixin,CreatedModifiedByMixin):classMeta:track_fields=('my_data',)# track changes on my_datatrack_related=('my_ref',)# track changes on a related modelmy_data=models.CharField(max_length=64,verbose_name="Very important data you want to track")my_ref=models.ForeignKey('SomeOtherModel',verbose_name="Very important relation",related_name='my_models')# Generic Relation to ChangeSetchangesets=ChangeSetRelation()Querying ChangeSets via the changesets relationBy inheriting from theRevisionModelMixinandCreatedModifiedByMixinmixins, and adding an attribute of typeChangeSetRelation(aGenericRelationfor the changeset), the following features are added to your model:Propertiescreated_by,created_at,last_modified_by,last_modified_atare made available for each object
(CreatedModifiedByMixin)Relationchangesetsis made available, allowing you to run queries like this one:MyModel.objects.filter(changesets__changeset_type='I', changesets__user__username='johndoe')Access ChangeSets and ChangeRecordsToDoYou can access the changeset by calling thechange_setproperty of an instance ofMyModelas shown in the following
example:print("------- CHANGE SETS (",len(somemodel.changesets),")---------")forchange_setinsomemodel.changesets:# print change_setprint("Change was carried out at ",change_set.date," by user ",change_set.user," on model ",change_set.object_type)print("  + CHANGE RECORDS (",len(change_set.change_records.all()),"): ")forchange_recordinchange_set.change_records.all():print("\t",change_record)print("\tIs change on a related field?",change_record.is_related)# related fields: we only know that something new has been added. we know the PK, but not the object itselfprint("\t\tChanged field ",change_record.field_name,"(",change_record.field_verbose_name,") from ",change_record.old_value,"(display:",change_record.old_value_display,") to")print("\t\t",change_record.new_value,"(display:",change_record.new_value_display,")")ifchange_record.is_related:print("\t\tRelated Object Info: ",change_record.related_object)# TODO:# change_set.created_at, change_set.created_by, change_set.last_modified_by, change_set.last_modified_atprint("-----")MaintainersThis repository is currently maintained bybeachmachineanx-mpoelzlPull Requests are welcome.LicenseDjango ChangeSet uses the BSD-3 Clause License, see LICENSE file.