Muhammad Saqib
Muhammad Saqib

Reputation: 121

Save Future Occurrences W.R.T event_id

class Occurrence(models.Model):
    last_updated = models.DateTimeField(default=timezone.now)
    time_modified = models.BooleanField(default=False)
    start_time = models.DateTimeField(_('start time'))
    end_time = models.DateTimeField(_('end time'))
    event = models.ForeignKey(Event, verbose_name=_('event'), editable=False)
    lead_technician = models.ForeignKey('mbi.Employee', related_name='tasks_lead')
    team = models.ManyToManyField('mbi.Employee', related_name='assigned_tasks', blank=True)
    vehicles = models.ManyToManyField('vehicles.Vehicle', related_name='assigned_tasks', blank=True)
    if request.method == "POST":
        form = EditOccurrenceForm(request.POST, occurrence=occurrence, user=request.user, save_all=True,changed_data=False)
        formset = file_formset(request.POST, request.FILES, instance=occurrence)
        if form.is_valid() and formset.is_valid():
            formset.save()
            occurrence = form.save()

Now below part i have done to achieve update future occurrences so, if user clicks on "Save All" button then

  1. Get all occurrences with same event.

  2. Then in loop i am submitting form with instance of occurrence which is "o" in the loop.

Now but problem is, all field are updating of future occurrences.

            if request.POST.get('save_all'):
                occurrences = Occurrence.objects.filter(event=occurrence.event) \
                                      .filter(start_time__gt=occurrence.start_time)
                if occurrences:
                    for o in occurrences:
                        form = EditOccurrenceForm(request.POST, occurrence=o, user=request.user, save_all=True)
                        if form.is_valid():
                            form.save()
            return HttpResponseRedirect(reverse(occurrence_detail, kwargs={'occurrence_id': occurrence.id}))


This is my Occurrence Model and the requirement is: When user changes any/Specific field while submitting form, then Future Occurrence W.R.T to event_id should be updated as well.

For example if an event has three Occurrences and from first occurrence user tries to change "team" and "vehicles" then only "vehicles and "team" should be changed in all other future occurrences.

Now I figured out one part which is getting future Occurrence but not Occurrences from the Past. But when changing the future Occurrences it's updating all occurrences all data, which is not required.

I hope I made myself clear while explaining.

Upvotes: 0

Views: 45

Answers (1)

dirkgroten
dirkgroten

Reputation: 20692

I would approach it this way:

  • You need to keep track of the data that was changed. Since you're changing an existing Occurrence, you should change your form to a ModelForm (you're not showing your form but the way you initialise it indicates it's a Form). That way, form.changed_data will tell you what was changed with respect to the initial Occurrence instance (form.instance). Otherwise, you'll have to write an equivalent changed_data method yourself, because the Form's changed_data will always give you that everything was changed since it compares to initial.
  • After you've save the changed Occurrence, you'll need to write a method that only saves the changed fields for the future occurrences. I would not reinitialise the form with the future instances to do that, as that leads to all fields being assigned the request.POST values. Write a new method on your form, (e.g. save_changed_data_to_occurence(self, occurrence)) that does that:
def save_changed_data_to_occurrence(self, occurrence):
    changed = False
    for field in self.changed_data:
        model_fields = [f.name for f in occurrence._meta.get_fields()]
        if field in model_fields:
            changed = True
            if field not in ['team', 'vehicles']:
                setattr(occurrence, field, self.cleaned_data[field])
            else:
                # ManyToMany relationship, use `set()`
                getattr(occurrence, field).set(self.cleaned_data[field])
    if changed:
        occurrence.save()
  • In your view, you just call form.save_changed_data_to_occurrence(o) for each occurrence in the future for the same event.

Upvotes: 1

Related Questions