Comments (3)
To clarify, we intend to use django-simple-history in a database which has a user interface, using the generic create and update views from Django, which I think causes the issue, as that one might have the different .add() and .save() actions in there causing the duplicate records.
We have now locally managed to fix it by removing duplicate history records (based on user and timestamp (to the second) before parsing them.
In case anyone is interested:
def remove_duplicate_records(self, object_history: HistoricalRecords) -> List[HistoricalChanges]:
"""
Removes duplicate history records based on user and timestamp.
This is to accommodate for that when changing m2m fields, django-simple-history creates 2 historical records.
One when the .add() is called one when .save() is called in Django's generic create and update views.
Only the first in the list of each set of duplicated entries needs to be kept, as that holds all the changes.
:param object_history: HistoricalRecords: List of historical records for an object containing potential
duplicates
:return: List[HistoricalChanges]: Deduplicated list of historical records for the object.
"""
deduplicated_records = [object_history[0]] # initiate with the latest change as first entry
for i in range(len(object_history) - 1):
previous_record = object_history[i]
current_record = object_history[i + 1]
previous_timestamp = previous_record.history_date.strftime('%Y-%m-%d %H:%M:%S')
current_timestamp = current_record.history_date.strftime('%Y-%m-%d %H:%M:%S')
# When the current record differs from the previous one on user and timestamp, add it to deduplicated
if current_record.history_user != previous_record.history_user or current_timestamp != previous_timestamp:
deduplicated_records.append(current_record)
return deduplicated_records
from django-simple-history.
I don't think it's a viable option fixing this (intended) behavior, unfortunately. This is because updating M2M fields necessarily changes a different table than the model's table - which happens in a separate transaction from updating the model's table (unless it's part of an atomic transaction, of course) - and since this library does not keep track of transactions, we have to create two historical records in these cases.
Update but do not save the m2m field of the instance holding the m2m field
I'm assuming you're talking about calling the add()
, remove()
or set()
M2M manager methods..? Because calling them will immediately change the M2M table, regardless of whether e.g. save()
has been called on the model object, in case you weren't already aware 🙂
from django-simple-history.
Other than that, thank you for posting the code that solved your problem!
Please reopen if you'd like to discuss alternative solutions 🙂
from django-simple-history.
Related Issues (20)
- Improve "clean old history" command to considering the number of entries HOT 1
- History for ManyToMany tables not being tracked HOT 4
- Add some clue from where in the code the update came from
- Instruction to install django-simple-history before exectuing runtests.py is missing
- Error with identifiers with '/' HOT 1
- Helper to merge / append to history records
- date_hierarchy with history_date
- Unique fields in django model translation with Simple History HOT 5
- Inappropriate verbiage in the signals documentation HOT 1
- Utils documentation missing for populate_history management command
- SimpleHistoryAdmin.history_view always use `AUTH_USER_MODEL` for generating the URL under "Changed By"
- `diff_against` does not detect changes on deletion history type
- Show diff in history_view
- as_of with Postgres generates a Sequential Scan with composite index enabled HOT 5
- Access foreign key of historic instance from model methods HOT 1
- [Question] How to prevent history from being created for a new object? Also how to set user to history after it has been created? HOT 2
- Updating M2M relations causes unnecessary DB queries HOT 11
- How to annotate the historical model to the QuerySet HOT 3
- not working abstract model HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-simple-history.