0

I have two update views accessed with different urls. In the first update view CreateType I set a variable in my initial called old_type. After I submit and go through other views I end up in my second UpdateView CreateSchedule. if i print self.initial in my second view I find the var old_type I have set in my first UpdateView for some reason.

First view

class CreateType(views.UpdateView):
    """
    Create type form
    """
    model = Group
    form_class = TypeForm
    template_name = 'create.html'
    extra_context = {'has_fifth_steps': False, 'active_step': 1, 'progress': 0}

    def get_object(self, queryset=None):
        object = super(CreateType, self).get_object(queryset)
        self.initial['old_type'] = object.type
        return object

    def form_valid(self, form):
        object = form.save()
        if object.type == Group.TYPE_SINGLE and self.initial['old_type'] == Group.TYPE_MULTIPLE:
            first_obj = Obj.objects.filter(group=object).values('id').first()
            if first_obj:
                Obj.objects.filter(group=object).exclude(id=first_obj['id']).delete()
        return redirect('create_obj.debtor', pk=object.pk)

My second view:

class CreateSchedule(views.UpdateView):
    """
    Schedule form
    """
    model = Group
    fields = []
    template_name = 'createschedule.html'

    def get_object(self, queryset=None):
        object = super(CreateSchedule, self).get_object(queryset)
        # if object.type == Group.TYPE_SINGLE:
        self.obj_object = Obj.objects.filter(group=object).first()
        return object

    def get_form(self, form_class=None):
        paymentschedule_formset = modelformset_factory(
            model=PaymentSchedule,
            form=PaymentScheduleForm,
            fields=('due_date', 'value'),
            validate_min=True,
            min_num=self.obj_object.number_of_payments,
            validate_max=True,
            max_num=self.obj_object.number_of_payments,
        )

        print(self.initial)
        return paymentschedule_formset(
            queryset=PaymentSchedule.objects.filter(obj=self.obj_object),
    )

    def get_context_data(self, **kwargs):
        context = super(CreateSchedule, self).get_context_data(**kwargs)
        if self.object.type == Group.TYPE_MULTIPLE:
            context['has_fifth_steps'] = True
            context['active_step'] = 5
        else:
            context['has_fifth_steps'] = False
            context['active_step'] = 4
        context['progress'] = 100
        return context

Not sure if I am doing something wrong or this is a normal behavior which doesn't make much sense to me.

Appreciate any help!

Edit:

Added urls.py

urlpatterns = [
path('create/<int:pk>/', sanad.CreateType.as_view(), name='create_obj.type'),
path('create/<int:pk>/payments-schedule', CreatesSchedule.as_view(), name='create_obj.schedule'),
]
devdob
  • 1,404
  • 12
  • 13

1 Answers1

3

You shouldn't ever modify self.initial. That is a dictionary defined at class level in the FormMixin, which is used by CreateView. If you modify that dict, that modification is visible by all views.

You shouldn't do this. Anyway, changing initial within get_object is the wrong thing to do. Instead, define the get_initial() method to return a new dictionary containing this value:

def get_initial(self):
    return {'old_type': self.object.type}

Now you shouldn't need to override get_object at all.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Thanks, I get your answer, may I ask how is the variable getting transferred between the views? I am trying to trace that with no avail. – devdob Mar 07 '19 at 12:32
  • And also, why is it that when I do `self.initial = {'old_type' : object.type}` instead of the above, it works as expected? – devdob Mar 07 '19 at 12:34
  • It's not getting transferred, as I said it is a class-level attribute defined in FormMixin, see https://github.com/django/django/blob/master/django/views/generic/edit.py#L12. Doing that defines a new *instance* variable, rather than modifying the class variable. See for example [this question](https://stackoverflow.com/questions/1680528/how-to-avoid-having-class-data-shared-among-instances). – Daniel Roseman Mar 07 '19 at 12:35