Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added the possibility to create a relation to the original model #536

Merged
merged 14 commits into from
Apr 5, 2019
Merged

Conversation

nick-traeger
Copy link
Contributor

@nick-traeger nick-traeger commented Mar 20, 2019

Description

i have created an optional parameter "related_name" which can be used to create another field "history_relation". This will then create a relation to the original entry.

Related Issue

No related issue

Motivation and Context

This should make filtering a little easier. For example, I can get all entries where a certain user has made changes.

How Has This Been Tested?

Added some unit tests (RelatedNameTest)

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have run the make format command to format my code
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have added my name and/or github handle to AUTHORS.rst
  • I have added my change to CHANGES.rst
  • All new and existing tests passed.

@nick-traeger
Copy link
Contributor Author

Is everything okay with the source code and merge request? And is there a chance that the feature will be implemented?

@rossmechanic
Copy link
Collaborator

Hey @nick-traeger. Really interesting PR. I've got a backlog of these (5 currently open) that I'm going to try to handle this weekend, but I'll take a look soon and try to get this into the next release.

Initial thoughts:
• Definitely want to have some sort of warning if you have a name clash (i.e. someone does `history = historical_records(related_name=history))
• Add docs

Overall, looks good tho. @ThePumpingLemma @kseever

@codecov-io
Copy link

codecov-io commented Apr 2, 2019

Codecov Report

Merging #536 into master will increase coverage by 0.04%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #536      +/-   ##
==========================================
+ Coverage   97.71%   97.75%   +0.04%     
==========================================
  Files          17       17              
  Lines         830      847      +17     
  Branches      114      117       +3     
==========================================
+ Hits          811      828      +17     
  Misses          8        8              
  Partials       11       11
Impacted Files Coverage Δ
simple_history/models.py 98.99% <100%> (+0.03%) ⬆️
simple_history/exceptions.py 100% <100%> (ø) ⬆️
...ory/management/commands/clean_duplicate_history.py 100% <0%> (ø) ⬆️
simple_history/utils.py 100% <0%> (ø) ⬆️
simple_history/admin.py 98.07% <0%> (+0.03%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2e7d9d3...63d5daf. Read the comment docs.

@nick-traeger
Copy link
Contributor Author

I have implemented a check that prevents the related_name from being equal to the history manager.

@nick-traeger
Copy link
Contributor Author

I have now extended the documentation. Is there anything else I should change?

@@ -432,6 +452,10 @@ def create_historical_record(self, instance, history_type, using=None):
for field in self.fields_included(instance):
attrs[field.attname] = getattr(instance, field.attname)

relation_field = getattr(manager.model, "history_relation", None)
if relation_field is not None:
attrs["history_relation"] = instance
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens here when the base object is deleted? I imagine something goes wrong, since you'll have a foreign key to a null object

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a bug which stored the id of the old instance. But now he stores None, which is no problem at all

model,
null=True,
on_delete=models.SET_NULL,
related_name=self.related_name,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably add db_constraint=False

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@barm barm added the accepted Issue accepted for completion label Apr 4, 2019
"history_relation": models.ForeignKey(
model,
null=True,
on_delete=models.SET_NULL,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually probably want to have models.DO_NOTHING here. If you set null, and then try to undelete an object, this pattern no longer works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepted and changed.

with self.assertRaises(RelatedNameConflictError):
register(Place, manager_name="history", related_name="history")

def test_deletion(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add one more test that deletes the object and then reverts it, and see if the history queries still work? Will approve after that. Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

self.assertEqual(Street.log.count(), 4)

def test_revert(self):
id = self.one.pk
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is a little confusing to me. Was hoping for something that would tell me that all of the previous historical records are still related to the reverted object, so:

id = self.one.id 
self.one.delete()

self.assertEqual(0, Street.objects.filter(pk=id).count())

old = Street.history.filter(id=id).first()
old.history_object.save()
self.assertEqual(4, old.history.count())

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially just want to make sure that the same key is reused and all the foreign keys still link to the same base object

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now test whether the object behaves as before and whether the relations still exist

CHANGES.rst Outdated
@@ -3,6 +3,10 @@ Changes

- remove reference to vendored library ``django.utils.six`` in favor of ``six`` (gh-526)

2.7.1 (2019-03-20)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The should be Unreleased until we release.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed that! Last fix and then I'll approve lol

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Collaborator

@rossmechanic rossmechanic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks @nick-traeger

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted Issue accepted for completion
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants