jazzband / django-simple-history

Store model history and view/revert changes from admin site.
https://django-simple-history.readthedocs.org
BSD 3-Clause "New" or "Revised" License
2.22k stars 481 forks source link

Creating ManyToMany records in the reverse with excluded fields #1408

Open dwasyl opened 1 month ago

dwasyl commented 1 month ago

In trying to create ManyToMany relations, ie (with the below example) Topping.objects.first().pizzas.add(pizza) fails, due to the excluded field on Topping.

It generates a HistoricalTopping() got unexpected keyword arguments: 'last_used date', based on simple_history/models.py:L740 when it creates the instance because the excluded field is included in the attrs.

With two models created like this:

class Pizza(models.Model):
    name = models.CharField(max_length=150)
    toppings = models.ManyToManyField("Topping", related_name="pizzas")

    history = HistoricalRecords(m2m_fields=[toppings])

class Topping(models.Model):
    name = models.CharField(max_length=150)
    last_used_date = models.DateTimeField(auto_now=True)

    history = HistoricalRecords(excluded_fields=["last_used_date"])

And then using it like:

topping = Topping.objects.first()
pizza = Pizza.objects.first()

# This fails with an unexpected keyword argument (for the last_used_date)
topping.pizzas.add(pizza)

# But this works with no errors at all
pizza.toppings.add(topping)

This testing was done on the latest release version, running Django 4.2. It's pretty clear that the problem is in the generating of the attrs used to create the history in create_historical_record, but I'm not sure how to prevent it from picking up excluded fields. Any ideas?