jazzband / django-recurrence

Utility for working with recurring dates in Django.
https://django-recurrence.readthedocs.org/
BSD 3-Clause "New" or "Revised" License
492 stars 190 forks source link

Validating form with RecurrenceField immediately updates model #149

Open nlittlejohns opened 5 years ago

nlittlejohns commented 5 years ago

I've noticed that calling is_valid() on a form which includes a RecurrenceField immediately updates the Recurrence object.

To reproduce Create a model with a RecurrenceField object and a ModelForm based on that object Include the following code in your form handling function (my model instance is called "event")

print(event.recurrences.rrules[0].byday)
if event_form.is_valid():
    print(event.recurrences.rrules[0].byday)

Use the ModelForm to change the recurrence rule from weekly on Sunday to weekly on Monday

Result [SU] [MO]

Is this expected behaviour? Perhaps it's unavoidable? It caught me a bit off guard when I was trying to do something a bit convoluted because my object was getting updated before I expected it to.

dominicrodger commented 5 years ago

That seems like a bug, though probably one that doesn't affect many people, since people typically will only call is_valid right before save (unless is_valid returns False for some other field for example).

nlittlejohns commented 5 years ago

Yeah, I think it's a pretty niche use case.

For reference, my use case is that I'm doing a Google Calendar-style "edit this and following events" type thing, and I'm doing this in the following (perhaps a non-ideal) way:

(Context: I have "event" objects which store recurrence information, then I have "occurrence" objects which are bulk-created based on the event's recurrence rules)

  1. Re-calculate and store the new "until" date for the original event to make it 1 day before the occurrence being updated
  2. Create a new event for the "this and following" occurrences, and generate these occurrences
  3. Delete the occurrences from the original event which are no longer valid

I'd like to do this by duplicating the original recurrence object and then updating it based on the contents of the form, but I'm having difficulty duplicating the object (for some reason I can't seem to do the standard object.pk=None and save()), and by the time I want to update the object, it's already been saved because of the is_valid() issue.

Anyway, it's a pretty niche use case, I should be able to work around it. Just ignoring it for now 🙂