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

History changes do not get tracked for ManyToMany field #614

Closed
martasd opened this issue Dec 11, 2019 · 7 comments
Closed

History changes do not get tracked for ManyToMany field #614

martasd opened this issue Dec 11, 2019 · 7 comments

Comments

@martasd
Copy link

martasd commented Dec 11, 2019

I have a model called Beo with a ManyToMany field organizers using a through model as suggested here:

class Beo(HistoryModel):
    ...
    organizers = ManyToManyField(
        UserProfile, related_name="organized_beos", blank=True,
        through="BeoOrganizer", through_fields=("beo", "organizer")
    )


class BeoOrganizer(HistoryModel):
    beo = ForeignKey(Beo, on_delete=CASCADE)
    organizer = ForeignKey(UserProfile, related_name="organized_beo", on_delete=CASCADE)

    class Meta(HistoryModel.Meta):
        verbose_name = "beo organizer"
        verbose_name_plural = "beo organizers"

    def __str__(self):
        return f"{self.beo} - {self.organizer}"

To use django-simple-history with multiple models, I have created an abstract class called HistoryModel, which creates historical records:

class HistoryModel(BaseModel):
    class Meta(BaseModel.Meta):
        abstract = True

    # History
    changed_by = ForeignKey(UserProfile, on_delete=SET_NULL, null=True, blank=True)
    history = HistoricalRecords(
        user_model=UserProfile, inherit=True, excluded_fields=["modified_at"]
    )

    @property
    def _history_user(self):
        return self.changed_by

    @_history_user.setter
    def _history_user(self, value):
        # History user can only be a user profile, not admin user
        if isinstance(value, SystemUser):
            self.changed_by = None
        else:
            self.changed_by = value

When I make changes to a Beo instance, history gets recorded as expected for beo instance itself. Everything works well here. When I make changes to organizers of a beo, however, the only changes recorded in beo_historicalbeoorganizer table are deletions (history_type is -). Neither creations nor updates get recorded.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Django model with history containing a ManyToMany field using through model
  2. Create the through model with history
  3. Create a new instance of the first model with a value in the ManyToMany field.
  4. + history_type record DOES NOT get created for the ManyToMany field.

Expected behavior
+ history_type record DOES get created for the ManyToMany field.

Environment

  • OS: Debian GNU/Linux 10
  • Django Simple History Version: 2.8
  • Django Version: 2.2.5
  • Database Version: PostgreSQL 11.6
@rossmechanic
Copy link
Collaborator

How are you calling these? As beo.add(beo_organizer)? I think they should send a post_save signal to add those changes – however, if they don't we can hook simple history into the m2m_changed signal and get it working there. I'd be happy to look at a PR if you want to take a shot at one.

@martasd
Copy link
Author

martasd commented Dec 12, 2019

When I call beo.organizers.add(user), the user does get added to the beo as expected, but the historical record does not get created. Could you please point me to the right place in the code to add this?

@rossmechanic
Copy link
Collaborator

https://github.com/treyhunner/django-simple-history/blob/b96a8fddafcb314fd7c2a8e4c48ab5d6045ef07a/simple_history/models.py#L163-L166

That's where we connect to post_save and post_delete signals. Would also want to connect to the m2m_changed signal

@martasd
Copy link
Author

martasd commented Dec 13, 2019

Thanks. I will take a look.

@carolynlawrence
Copy link

carolynlawrence commented Jan 22, 2020

Just wanted to chime in here that I've just run into this issue, and a quick work-around that seems to be working ok for me to at least get create changes to be recorded is to call create instead of add, e.g. for @martasd code example above:

BeoOrganizer.objects.create(beo=beo_instance, organizer=organizer_instance)

instead of

beo_instance.organizers.add(organizer_instance)

@jeking3
Copy link
Contributor

jeking3 commented Sep 16, 2021

Also see #399

@ddabble
Copy link
Member

ddabble commented Feb 26, 2024

This seems either resolved or stale, so closing. Please reopen if that's not the case 🙂

@ddabble ddabble closed this as completed Feb 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants